我是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 }
并且他们之间有一个one-to-many从Employee到的关系Address (每个员工的记录中可以有多个地址) 。方便地忽略了一个事实,即一个以上的员工可能居住在同一地址。
one-to-many
Employee
Address
我从内存中的对象(NHibernate实体)的角度理解了这一点。我正在努力的是映射文件(这里我举一个简单的例子)。到目前为止,这是我想出的:
// 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>
仅提供一些提示,总结了我在使用NHibernate时发现的最合适的标准。
1)如果在持久性 (DB列)中 存在 双向* 引用,则也以 双向 代码表示。 __C# *
C#
换句话说,如果 孩子 引用了 parent ,那么 父母 应该引用 child 。
public class Employee { ... public virtual IList<Address> { get; set; } } public class Address { ... public virtual Employee Employee { get; set; } }
这按原样表示业务域。地址属于雇员,而雇员属于地址。
如果出于某些原因我们确实想限制此限制,则应该进行protected修改,但仍将引用保留在C#
protected
2)使用inverse="true"。仅当我们同时映射了两侧(如上)时,才可以使用它,这将导致更多“预期和优化”的INSERT和UPDATE脚本。
inverse="true"
在这里阅读更多:
inverse =“ true”示例和 mkyong的解释
3)几乎在任何地方都使用批量获取映射。这样可以避免在查询过程中出现1 + N个问题。阅读更多:
有关批量提取的一些细节
4)如果一个对象(in our case Employee)是root ( 另一个对象 没有它就没有多大意义) -使用级联。阅读更多:
(in our case Employee)
root
nhibernate-通过更新父级创建子级,还是显式创建?
映射摘要中的规则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,别忘了分配关系的双方 (在创建过程中最关键)
inverse="true
原因是:
我们指示NHibernate-另一边 _(Address)_负责持久关系。但是要正确执行此操作,Address需要参考Employee-才能将其ID保留在“地址”表的列中。
因此,这应该是创建新地址的标准代码
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()来隐藏这种复杂性,但是设置双方都是很好的方法。
AddAddress()