У меня есть иерархия с тремя уровнями объектов: Customer-Order-Line, которую я хотел бы получить полностью для данного клиента, используя ISession.Get (id). У меня есть следующие фрагменты XML:NHibernate Eager Извлечение на нескольких уровнях
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
До сих пор это выглядит good - SQL возвращает правильный набор записей (только с одним отдельным orderid), но когда я запускаю тест для подтверждения правильного количества объектов (из NH) для ордеров и строк, я получаю неправильные результаты
I должен получить (из моих тестовых данных), 1xOrder и 4xLine, однако я получаю 4xOrder и 4xLine. Похоже, что NH не признает «повторяющуюся» группу информации о заказе в результирующем наборе и не правильно «повторно использует» объект Ордера.
Я использую все целые идентификаторы (PK), и я попытался реализовать IComparable из T и IEquatable из T, используя этот идентификатор, в надежде, что NH увидит равенство этих объектов. Я также попробовал переопределить Equals и GetHashCode, чтобы использовать идентификатор. Ни одна из этих «попыток» не преуспела.
Является ли «многоуровневая выборка» поддерживаемой операцией для NH, и если да, требуется ли настройка XML (или какой-либо другой механизм) для ее поддержки?
NB: Я использовал решение 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. Это необходимо для новых (переходных) сущностей, иначе они не будут иметь идентификатор изначально (моя модель предоставила их при сохранении).
[Этот ответ] (http://stackoverflow.com/questions/5266180/fighting-cartesian-product-x-join-when-using-nhibernate-3-0-0/5285739#5285739) помог мне понять, как использовать запросы QueryOver и Future, чтобы охотно забирать детей и внуков, не возвращая дубликатов. Этот метод включает разбиение задачи на отдельные SQL-запросы, которые выполняются в одном обращении к базе данных. – 2011-10-20 20:29:56