我有一个 3 级实体层次结构:Customer-Order-Line,我想使用 ISession.Get(id) 为给定客户完整检索它。我有以下 XML 片段:
客户.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>
我使用了 fetch="join" 属性来表示我想为每个父级获取子实体,这已经构建了正确的 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),但是当我运行测试以确认 Orders 和 Lines 的正确实体数量(来自 NH)时,我得到了错误的结果
我应该(从我的测试数据中)得到 1xOrder 和 4xLine,但是,我得到了 4xOrder 和 4xLine。NH 似乎没有识别结果集中的“重复”订单信息组,也没有正确“重用”订单实体。
我正在使用所有整数 ID (PK),并且我尝试使用此 ID 实现 T 的 IComparable 和 T 的 IEquatable,希望 NH 会看到这些实体的相等性。我还尝试覆盖 Equals 和 GetHashCode 以使用 ID。这些“尝试”都没有成功。
NH 是否支持“多级提取”操作,如果支持,是否需要 XML 设置(或其他机制)来支持它?
注意:我使用了 Sirocco 的解决方案,对我自己的代码进行了一些更改,最终解决了这个问题。对于所有集合,xml 需要从包更改为集合,并且实体本身已更改为实现 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(我的模型在保存时提供了它们)。