考虑这两个类之间的关系
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,它可以按预期工作。知道为什么吗?
答案 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
进行过滤,则根本不需要操纵客户(对象,表格)。