我有一个3级的实体层次结构:Customer-Order-Line,我想使用ISession.Get(id)为给定的客户完整检索。我有以下XML片段:NHibernate渴望获取多个级别
customer.hbm.xml:
<bag name="Orders" cascade="all-delete-orphan" inverse="false" fetch="join">
<key column="CustomerID" />
<one-to-many class="Order" />
</bag>
order.hbm.xml:
<bag name="Lines" cascade="all-delete-orphan" inverse="false" fetch="join">
<key column="OrderID" />
<one-to-many class="Line" />
</bag>
我已经使用了取= “加入” 属性,并指示我想为每个父代获取子实体,并且这构建了正确的SQL:
SELECT
customer0_.ID AS ID8_2_,
customer0_.Name AS Name8_2_,
orders1_.CustomerID AS CustomerID__4_,
orders1_.ID AS ID4_,
orders1_.ID AS ID9_0_,
orders1_.PostalAddress AS PostalAd2_9_0_,
orders1_.OrderDate AS OrderDate9_0_,
lines2_.OrderID AS OrderID__5_,
lines2_.ID AS ID5_,
lines2_.ID AS ID10_1_,
lines2_.[LineNo] AS column2_10_1_,
lines2_.Quantity AS Quantity10_1_,
lines2_.ProductID AS ProductID10_1_
FROM Customer customer0_
LEFT JOIN [Order] orders1_
ON customer0_.ID=orders1_.CustomerID
LEFT JOIN Line lines2_
ON orders1_.ID=lines2_.OrderID
WHERE customer0_.ID=1
到目前为止,好 - SQL返回正确的一组记录(只有一个独特的OrderID),但是当我运行一个测试,以确认订单和线实体(从NH)的正确数目,我得到错误的结果
我应该(从我的测试数据),1xOrder和4xLine,但是,我得到4xOrder和4xLine。看起来NH并不认可结果集中“重复”的订单信息组,也没有正确地“重复使用”订单实体。
我正在使用所有的整数ID(PK),并且我尝试过使用这个ID实现T和T的IEquatable的IComparable,希望NH能看到这些实体的相等性。我也试过重写Equals和GetHashCode来使用ID。这些“尝试”都没有成功。
NH是否支持“多级提取”操作,如果有,是否需要XML设置(或其他某种机制)来支持它?
注:我用热风的解决方案与我自己的代码进行一些修改,终于解决了这一个。 xml需要从bag更改为set,对于所有集合,并且实体本身已更改为实现IComparable <>,这是要建立唯一性集合的要求。
public class BaseEntity : IComparable<BaseEntity>
{
...
private Guid _internalID { get; set; }
public virtual Guid ID { get; set; }
public BaseEntity()
{
_internalID = Guid.NewGuid();
}
#region IComparable<BaseEntity> Members
public int CompareTo(BaseEntity other)
{
if (ID == Guid.Empty || other.ID == Guid.Empty)
return _internalID.CompareTo(other._internalID);
return ID.CompareTo(other.ID);
}
#endregion
...
}
请注意使用InternalID字段。这对于新(瞬态)实体是必需的,否则最初他们不会有ID(我的模型在保存时会提供它们)。
[这个答案](http://stackoverflow.com/questions/5266180/fighting-cartesian-product-x-join-when-using-nhibernate-3-0-0/5285739#5285739)帮助我看看如何使用QueryOver和Future查询来热切地获取子孙,而不会返回重复项。该技术涉及将任务分解成单独的SQL查询,这些SQL查询在数据库的一个往返中执行。 – 2011-10-20 20:29:56