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

如何引用NHibernate中关系的类和Id属性,nhibernate,mapping,foreign-key-relationship,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;s

考虑这两个类之间的关系

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属性,我同意这不是最漂亮的做事方式。由于只有Customer属性,我可以轻松地请求Order.Customer.CustomerId来获取客户Id

但在这种情况下,NHibernate将触发对数据库的请求以加载该客户,并且有一些(实际上很多)情况我只需要订单的CustomerId。在这种情况下,Order类中的CustomerId将是有用的,并且需要较少的数据库访问。(如果我错了,请纠正我)

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

属性CustomerId将始终具有客户的Id,而属性Customer将仅在我想加载时由lazy加载(比如获取客户的名称)。Microsoft实体框架允许这样做

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

更新

按照回答说明,我做了一个测试,试图检查NHibernate没有按预期工作的原因,并发现了一些有趣的事情:默认情况下,NHibernate不会在Order.Customer.CustomerId处访问数据库,如果我不使用Accessor.Field mappingCustomerId属性


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

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

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


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

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

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


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

只能写入一个属性。我建议这样映射两者(我们使用这种方法):

阶级

映射

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

现在,您可以在读取操作中以相同的方式操作这两个属性(例如过滤)。分离订单的投标必须设置
客户
,而
客户ID
为只读

因此,对于写操作,您只能(而且应该)使用一个属性


好处是,如果只需要按客户
ID
进行筛选,则根本不必操作客户(对象、表)。

只有一个属性可以写入。我建议这样映射两者(我们使用这种方法):

阶级

映射

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

现在,您可以在读取操作中以相同的方式操作这两个属性(例如过滤)。分离订单的投标必须设置
客户
,而
客户ID
为只读

因此,对于写操作,您只能(而且应该)使用一个属性


好处是,如果只需要按客户
ID
进行筛选,则根本不必操作客户(对象、表)。

关于order.Customer.ID调用数据库的说法是错误的。我建议你放下外键。因此,q1和q2是redundant@Rippo当前位置我在penfold的回答中所做的评论相同:我可能做错了什么,但在一次测试中,a.B.Id确实进入了数据库。是关于多对一映射的吗?有必要急切吗?@RogerKiihl:如果没有看到映射和测试代码,就无法判断。你能用这些类的映射和你使用的测试代码更新你的问题吗?@penfold:我刚刚更新了de问题。它奏效了,但我发现了一些意想不到的事情。谢谢你的帮助。你对order.customer.id向数据库打电话是错误的。我建议你放下外键。因此,q1和q2是redundant@Rippo当前位置我在penfold的回答中所做的评论相同:我可能做错了什么,但在一次测试中,a.B.Id确实进入了数据库。是关于多对一映射的吗?有必要急切吗?@RogerKiihl:如果没有看到映射和测试代码,就无法判断。你能用这些类的映射和你使用的测试代码更新你的问题吗?@penfold:我刚刚更新了de问题。它奏效了,但我发现了一些意想不到的事情。谢谢你的帮助。我可能做错了什么,但在一次测试中,a.B.Id确实进入了数据库。是关于多对一映射的吗?是不是很急切?经过一些测试,我能够验证答案是正确的。但是当映射的id属性(Customer.CustomerId)使用默认的访问器映射时,这种默认行为会起作用(仍然不知道为什么)。@RogerKiihl我对此感到非常惊讶,因为访问类型不应该影响延迟加载。唯一应该影响它的是
lazy=“无代理”