nhibernate 4.0中的双向关系
我有一个代码在NHibernate 3.1上完美运行,但是当它不能在NHibernate 4.0上运行时
所以,这就是阶级关系
public class Employee : BaseEntity { ... public Department Dept { get; set; } } public class Department : BaseEntity { ... public IList Employees { get; set; } }
对于映射,我们有这个
DepartmentMap : ClassMap { Table("...."); HasMany(x => x.Employees).KeyColumn("DeptId").Not.KeyNullable(); } EmployeeMap : ClassMap { Reference(x => x.Dept).Column("DeptId"); }
当我添加这样的员工时
var dept = session.Load(deptId); newEmployee.Dept = dept; session.Save(newEmployee);
但这是一个错误:
NHibernate.PropertyValueException:not-null属性引用null或transient值
我读到我必须以两种方式添加关系,所以我将其修改为此
var dept = session.Load(deptId); newEmployee.Dept = dept; dept.Employees.Add(newEmployee); session.Save(newEmployee);
但现在我有这个错误:
NHibernate.PropertyValueException:错误使…的属性值脱水.System.IndexOutOfRangeException:此SqlParameterCollection的索引7无效,Count = 7。
所以,我想知道如何修复它以及我可以在哪里阅读有关双向的NHibernate变化
第一个问题 – 双向映射
我们应该始终指定关系的双方。 好吧, 总是?!? 这是优秀的做法。
但是 ,如果我们想使用.Load()
来检索parent
(Department) – 我们不应该指定parent.Chidren.Add()
。
Load()
是如何获取“假”(代理)实例的聪明方式,仅由该实体的ID表示(很难创建正确的INSERT语句)
所以,在这种情况下我们应该避免dept.Employees.Add(newEmployee);
– 我们根本不需要加载部门
// existing parent - but NHibernate just creates a proxy with expected ID var dept = session.Load(deptId); // child Employee is provided with parent reference - it is enough newEmployee.Dept = dept; // this will not help, just will execute SELECT - no benefit // dept.Employees.Add(newEmployee); // save and it should work session.Save(newEmployee);
第二个(真实)问题 – 双重映射
虽然它在问题代码片段中不可见,但我敢打赌,Employee实际上有这个def和映射
public class Employee : BaseEntity { ... // reference public virtual Department Dept { get; set; } // reference_ID also mapped as integer public virtual int? DeptId { get; set; } } EmployeeMap : ClassMap { Reference(x => x.Dept).Column("DeptId"); Map(x => x.DeptId) // with .Not.Nullable() by code or convention ; }
所以 – 我们在C#中有两个属性属于一个SQL列。 我会说,这绝对没问题,但我们必须确保我们稍微调整一下。 整数应该可以为空并且必须是只读的
EmployeeMap : ClassMap { Reference(x => x.Dept).Column("DeptId"); Map(x => x.DeptId) .Nullable() .Insert(false) .Update(false); // as far as I rememeber syntax to replicate //
我找到了解决问题的方法:解决问题的方法是将Inverse添加到父文件的映射中。 因此,部门的映射将是:
DepartmentMap : ClassMap { Table("...."); HasMany(x => x.Employees).KeyColumn("DeptId").Inverse().Not.KeyNullable(); }