nhibernate 4.0中的双向关系

时间:2015-05-07 20:57:50

标签: c# nhibernate fluent-nhibernate nhibernate-mapping fluent-nhibernate-mapping

我有一个在NHibernate 3.1上完美运行的代码,但是当它不能在NHibernate 4.0上运行时

所以,这就是阶级关系

public class Employee : BaseEntity
{
    ...
    public Department Dept { get; set; }
}

public class Department : BaseEntity
{
    ...
    public IList<Employee> Employees { get; set; }
}

我们有这个

的映射
DepartmentMap : ClassMap<Department>
{
     Table("....");
     HasMany(x => x.Employees).KeyColumn("DeptId").Not.KeyNullable();
}


EmployeeMap : ClassMap<Employee>
{
     Reference(x => x.Dept).Column("DeptId");
}

当我添加像这样的员工时

var dept = session.Load<Department>(deptId);
newEmployee.Dept = dept;
session.Save(newEmployee);

但这是一个错误:

  

NHibernate.PropertyValueException:not-null属性引用null   或瞬态值

我读到我必须以两种方式添加关系,所以我将其修改为

var dept = session.Load<Department>(deptId);
newEmployee.Dept = dept;
dept.Employees.Add(newEmployee);
session.Save(newEmployee);

但现在我有这个错误:

  

NHibernate.PropertyValueException:使属性值脱水错误   for ... System.IndexOutOfRangeException:此索引7无效   带有Count = 7的SqlParameterCollection。

所以,我想知道如何修复它以及我可以在哪里阅读有关双向的NHibernate变化

2 个答案:

答案 0 :(得分:0)

第一期 - 双向制图

我们应该始终指定关系的双方。那么,总是?!?这是一种优秀的做法。

以防我们想要使用 .Load() 来检索parent(部门) - 我们应该需要分配parent.Chidren.Add()

Load()是如何获得&#34;假的&#34; (代理)实例,仅由该实体的ID表示(足以创建正确的INSERT语句)

所以,在这种情况下,我们应该避免dept.Employees.Add(newEmployee); - 我们根本不需要加载部门

// existing parent - but NHibernate just creates a proxy with expected ID
var dept = session.Load<Department>(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);

第二(真实)问题 - 双重映射

虽然它在问题代码片段中不可见,但我敢打赌,员工实际上有这个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<Employee>
{
     Reference(x => x.Dept).Column("DeptId");
     Map(x => x.DeptId)
         // with .Not.Nullable() by code or convention
         ; 
}

所以 - 我们在C#中有两个属性属于一个SQL列。我会说,这绝对没问题,但我们必须确保我们稍微调整一下。整数应该是可空的并且必须是只读的

EmployeeMap : ClassMap<Employee>
{
     Reference(x => x.Dept).Column("DeptId");
     Map(x => x.DeptId)
        .Nullable()
        .Insert(false)
        .Update(false); // as far as I rememeber syntax to replicate
      // <property name="DeptId" insert="false" update="false" not-null="false />
}

那发生了什么?什么是两个例外?

  

NHibernate.PropertyValueException:not-null属性引用null或transient值

上述问题意味着还提供了NHibernate期望的属性DeptId

  

NHibernate.PropertyValueException:使...的属性值脱水错误.System.IndexOutOfRangeException:此SqlParameterCollection的索引7无效且Count = 7.

这种问题通常是双重映射 - 两个属性到一列。大多数情况下,由于引用和引用ID被映射到一列......

即使问题不是直接与 int? DeptId 相关 - 我希望这能为您提供足够的信息来揭示真正的罪魁祸首。

答案 1 :(得分:0)

我找到了解决问题的方法: 该问题的解决方法是将Inverse添加到父文件的映射中。 因此,部门的映射将是:

DepartmentMap : ClassMap<Department>
{
     Table("....");
     HasMany(x => x.Employees).KeyColumn("DeptId").Inverse().Not.KeyNullable();
}