如何在NHibernate中引用关系的类和Id属性

时间:2013-03-19 20:52:01

标签: nhibernate mapping foreign-key-relationship

考虑这两个类之间的关系

public class Order
{
  public int OrderId {get;set;}
  public int CustomerId {get;set;}  // Should this be here?
  public Customer Customer{get;set}
}

public class Customer
{
  public int CustomerId {get;set;}
  public string Name {get;set;}
}

我知道我不需要订单上的 CustomerId 属性,我同意它不是最美好的OO方式。只有Customer属性,我可以轻松请求 Order.Customer.CustomerId 来获取客户的ID。

但在这种情况下,NHibernate将触发向数据库加载该客户的请求,并且有一些(实际上很多)案例我只需要订单的 CustomerId 。在这种情况下,订单类中的 CustomerId 将非常有用,并且会减少对数据库的访问。 (如果我对此有误,请纠正我)。

问题1 :有没有办法告诉NHibernate我希望两个属性始终更新?

属性 CustomerId 将始终具有客户的ID,并且只有在我想要的情况下才会懒惰地加载客户属性(让我们说获取客户的名字) )。 Microsoft Entity Framework允许这样做。

问题2 :如果不可能,我应该担心吗?

更新

按照答案说明我做了一个测试,试图检查为什么(在我的情况下)NHibernate没有按预期工作并发现一些有趣的东西: NHibernate默认情况下不会在Order.Customer.CustomerId上点击数据库strong>我不使用Accessor.Field映射 CustomerId属性。

使用默认的Accessor,它可以按预期工作。知道为什么吗?

2 个答案:

答案 0 :(得分:4)

NHibernate的默认行为是仅在访问Id时不加载对象。另一个问题已经回答了我在下面引用过的here

如果从数据库中检索A,则访问A.B.Id,这将无法访问数据库。如果您访问Id字段之外的任何其他属性,它将导致NHibernate从数据库中检索B.

总而言之,调用Order.Customer.CustomerId不会触发NHibernate使用CustomerId查询客户表中行的数据库,因此最好从Order类中删除CustomerID。

答案 1 :(得分:1)

只有一个属性可写。我建议像这样映射(我们正在使用这种方法):

public int CustomerId {get;set;}  // Should this be here?
public Customer Customer{get;set} // Answer: yes

映射

<many-to-one name="Customer" column="CustomerId"  />
<property  name="CustomerId" column="CustomerId" insert="false" update="false" />

现在,您可以以相同的方式使用 Read 操作中的两个属性进行操作(例如,过滤)。分离订单的出价必须设置为Customer,而CustomerId为只读。

因此,对于写入操作,您可以(并且您应该)仅使用一个属性。

好处是,如果您只需要通过客户 ID进行过滤,则根本不需要操纵客户(对象,表格)。