用NHibernate映射一对多的最简单正确的方法

我是NHibernate和C#的新手,所以请温柔!

我有以下两个NHibernate实体:

Employee { private long _id; private String _name; private String _empNumber; private IList<Address> _addresses; //Properties... } 

 Address { private long _id; private String _addrLine1; private String _addrLine2; private String _city; private String _country; private String _postalCode; //Properties } 

并且它们具有从EmployeeAddress one-to-many关系(每个员工在其logging中可以有多个地址) 。 方便地忽略一个以上员工可以居住在同一个地址的事实。

我从内存中的对象(NHibernate实体)的angular度理解这一点。 我正在努力的是映射文件(我在这里是一个简单的例子)。 这是我到目前为止所提出的:

 // Intentionally left out XML and <hibernate-mapping> // Mappings for class 'Employee'. --> <class name="Employee" table="Employees"> <id name="ID"> <generator class="native"> </id> <property name="Name" /> <property name="EmpNumber" /> <bag name="Addresses"> <key column="AddressId" /> <one-to-many class="Address" /> </bag> </class> 

 // Intentionally left out XML and <hibernate-mapping> . // Mappings for class 'Address' <class name="Address" table="Addresses"> <id name="ID"> <generator class="native"> </id> // Intentionally left out name="Employee" // as I don't have corresponding field in Address entity. <many-to-one class="Employee" column="EmployeeID" cascade="all" /> <property name="AddrLine1" /> <property name="AddrLine2" /> <property name="City" /> <property name="Country" /> <property name="PostalCode" /> </class> 
  1. 它是否正确?
  2. 如果不是,那么我在这里所缺less的就是Address实体中的一个字段,它是对相应Employee实体的引用。 但如果是这样的话,我不明白为什么这是必需的:我不需要从Employee获取Address ,只能反过来…

总结了我在使用NHibernate时发现的最合适的标准。

1)如果存在双向引用(DB列) ,则也可以用C#代码双向表示。

换句话说,如果一个孩子提到父母父母应该参考孩子

 public class Employee { ... public virtual IList<Address> { get; set; } } public class Address { ... public virtual Employee Employee { get; set; } } 

这代表了业务领域。 地址属于员工,员工属于地址。

如果我们由于某些原因想要限制这个,我们应该protected修饰符,但是仍然保留在C#的引用

2)使用inverse="true" 。 这只能在我们映射双方(如上所述)时使用,并且会导致更多的“预期和优化”插入和更新分拣

在这里阅读更多:

inverse =“true”的例子和 mkyong的解释

3)使用批量获取映射几乎任何地方。 这将避免查询期间的1 + N问题。 阅读更多:

很less有关批量抓取的细节

4)如果一个对象(in our case Employee)root (另一个没有这个对象,那么这个对象没什么意义) – 使用级联。 阅读更多:

nhibernate – 通过更新父项创build子项,还是明确创build?

规则2,3,4中的映射片段:

 <class name="Employee" ... batch-size="25"> ... <bag name="Addresses" lazy="true" inverse="true" batch-size="25" cascade="all-delete-orphan" > // wrong! This columns is the same as for many-to-one //<key column="AddressId" /> // it is the one column expressing the relation <key column="EmployeeId" /> <one-to-many class="Address" /> </bag> <class name="Address" ... batch-size="25"> ... <many-to-one not-null="true" name="Employee" column="EmployeeID" /> 

3)如果我们使用inverse="true不要忘记分配关系的两边(在创作过程中主要是关键)

原因是:

我们指导NHibernate – 对方Address负责维持关系。 但为了做到这一点,该Address需要引用Employee – 以便能够将其ID保存到地址表中的列中。

所以这应该是创build新地址的标准代码

 Employee employee = ... // load or create new Address address = new Address { ... Employee = employee, // this is important }; Employee.Addresses.Add(address); session.SaveOrUpdate(employee); // cascade will trigger the rest 

我们也可以引入一些像AddAddress()这样的方法来隐藏这个复杂性,但是设置双方是一个很好的方法。

您应该在one-to-many关系中添加级联all-delete-orphan ,如果删除Employee ,地址也将被删除。

如果你不需要Employee引用,像这样创buildinverse=false关系: 这里