使用SaveOrUpdate时Fluent NHibernate未设置子对象Id的原因
问题解决:Fluent NHibernate自引用关联外键为Null的问题
问题场景
实体类定义:
public class Error { public virtual long Id { get; set; } public virtual string Message { get; set; } public virtual Error InnerException { get; set; } }
映射类定义:
class ErrorMap : ClassMap<Error> { public ErrorMap() { Id(x => x.Id); Map(x => x.Message); HasOne(x => x.InnerException).Cascade.All(); } }
保存代码:
using (var transaction = m_protokollSession.BeginTransaction()) { Error err = new Error() { Message = "Outher", InnerException = new Error() { Message = "Inner", } }; m_protokollSession.SaveOrUpdate(err); transaction.Commit(); }
执行后发现外层Error数据行的InnerException_id字段为null,未正确关联内层Error的Id。
原因分析
HasOne在NHibernate中是用于基于主键的一对一关联,即两个实体共享同一个主键值,这种场景下NHibernate不会生成常规的外键字段来维护关联。而你的场景是自引用的多对一关联(一个外层Error关联一个内层Error,内层Error可以被多个外层Error引用),这种情况应该使用References来映射,它才是专门用于处理多对一关联、维护外键字段的映射方式。
解决方案
将映射类中的HasOne替换为References,并可根据需要指定外键名称(如果不指定,NHibernate会默认生成类似InnerException_id的字段名,和你当前的字段名一致):
class ErrorMap : ClassMap<Error> { public ErrorMap() { Id(x => x.Id); Map(x => x.Message); // 替换HasOne为References,维护多对一关联 References(x => x.InnerException) .Cascade.All() // 保持级联操作,确保内层Error被自动保存 .Nullable(); // 允许外键为null,因为不是所有Error都有InnerException } }
修改后重新执行保存代码,外层Error的InnerException_id字段会被正确赋值为内层Error的Id,同时级联操作会自动保存内层Error到数据库。
内容的提问来源于stack exchange,提问作者Gener4tor
相关产品推荐
相关产品推荐

