gpt4 book ai didi

c# - 使用 NHibernate 映射一对多的最小且正确的方法

转载 作者:太空狗 更新时间:2023-10-29 18:28:56 26 4
gpt4 key购买 nike

我是 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有一个一对多关系员工的记录中可以有多个地址)。方便地忽略不止一名员工可能居住在同一地址这一事实。

我是从内存中对象的角度来理解的(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>
  1. 这是正确的吗?
  2. 如果没有,我似乎在这里缺少的是 Address 中的一个字段实体,它是对相应 Employee 实体的引用。但是如果所以,我不明白为什么需要这样做:我不需要获取来自 EmployeeAddress,反之亦然...

最佳答案

只是一些提示,总结了我在使用 NHibernate 时发现的最合适的标准。

1) 如果persitence(DB列)中有bi-directional引用,用C#代码bi表示-定向也是如此。

换句话说,如果一个 child 引用了应该引用了 child

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

这表示业务域的原样。地址属于员工,员工属于地址。

If we for some reasons really want to restrict that, we should rather protected modifier, but still keep the reference in C#

2) 使用inverse="true"。这只能在我们映射两侧(如上所述)时使用,并且会导致更多“预期和优化”的 INSERT 和 UPDATE 脚本

在这里阅读更多:

inverse = “true” example and explanation通过 mkyong

3) 几乎无处不在地使用批量获取映射。这将避免在查询期间出现 1 + N 问题。阅读更多:

few details about batch fetching

4) 如果一个对象 (在我们的例子中是 Employee)root (如果没有它,另一个对象就没有多大意义) - 使用级联。阅读更多:

nhibernate - Create child by updating parent, or create explicitly?

映射片段中的规则 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,不要忘记分配关系的两边(在创建过程中最关键)

原因是:

we instruct NHibernate - the other side (Address) is responsible for persisting relation. But to do that properly, that Address needs to have reference to Employee - to be able to persist its ID into its column in Address table.

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

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() 来隐藏这种复杂性,但设置两侧是一个很好的做法。

关于c# - 使用 NHibernate 映射一对多的最小且正确的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29985158/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com