我试图让NHibernate在一对一的映射方案中保存完整的对象图。我有以下课程
public class Employee : EntityBase
{
public virtual string EmployeeNumber { get; set; }
public virtual Address ResidentialAddress {get; set; }
}
public class Address : EntityBase
{
public virtual string AddressLine1 { get; set; }
public virtual string AddressLine2 { get; set; }
public virtual string Postcode { get; set; }
public virtual string City { get; set; }
public virtual string Country { get; set; }
public virtual Employee Employee { get; set; }
}
我试图在这里使用一对一的映射,这样一个员工只有一个住址。我的映射在
之下<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain">
<class name="Employee">
<id name="Id" generator="hilo" />
<property name="EmployeeNumber" length="10" />
<one-to-one name="ResidentialAddress" class="Address" property-ref="Employee" cascade="all" />
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain">
<class name="Address">
<id name="Id" generator="hilo" />
<property name="AddressLine1"/>
<property name="AddressLine2" />
<property name="Postcode" />
<property name="City" />
<property name="Country" />
<many-to-one name="Employee" class="Employee" unique="true" />
</class>
</hibernate-mapping>
我使用以下代码来保存员工对象的实例
using (var transaction = Session.BeginTransaction())
{
id = Session.Save(new Employee
{
EmployeeNumber = "123456789",
ResidentialAddress = new Address
{
AddressLine1 = "Address line 1",
AddressLine2 = "Address line 2",
Postcode = "postcode",
City = "city",
Country = "country"
}
});
transaction.Commit();
}
在上述情况下,返回Employee的地址上的外键始终为null。但是,如果我在ResidentialAddress
类上更改R Employee
属性,以便Employee
属性始终正确填充,如下所示
private Address address;
public virtual Address ResidentialAddress
{
get { return address; }
set
{
address = value;
if (value != null) value.Employee = this;
}
}
这使它完美地运作。为什么我必须设置ResidentialAddress.Employee
?我错过了映射中的内容吗? NHibernate是否应该自动保存完整的对象图(因此确定正确的外键值)。
以上工作代码与我有关,因为在从数据库加载实体期间从NHiberante调用时可能会产生问题。
答案 0 :(得分:1)
你没有遗漏任何东西。
我们(开发人员)应始终关注设置任何双向关系的两端。
当我们使用one-to-many
(没有反向=&#34; true&#34;)而没有设置many-to-one
时,我们总是会遇到冗余且无效的序列SQL语句:
不建议这样做:6.8. Bidirectional Associations:
...非反面用于将内存中表示保存到数据库。如果两者都触发更改,我们将获得一个不必要的INSERT / UPDATE,甚至可能是外键冲突!对于双向一对多关联,当然也是如此......
所以,这是一对多,多对一。
如果是一对一
如上所述,没有集合持久存在。没有人在中间,会照顾另一端,并且发出“无效的”#34; INSERT和稍后更新。 NHibernate将使用Employee
和Address
的标准实体持久性。
关系(员工地址)的每个关联结束都有自己的持久性。这些可以在级联中触发(通常好的想法是<one-to-one ... cascade="all" />
)
但是每个持久化程序都需要足够的信息来创建正确的INSERT或UPDATE语句。即甚至C#地址必须知道其员工。 Address persister,将单独处理INSERT / UPDATE,只能访问Address实例。
总结:我们必须在代码中设置两端....即使我们没有强制(具有可空父列的非逆子映射),这也是很好的做法。
BTW:一旦从数据库加载,我们希望 NHibernate 将设置两者结束...为什么我们不应该这样做?