Tengo una jerarquía de entidades de 3 niveles: Customer-Order-Line, que me gustaría recuperar en su totalidad para un cliente determinado, utilizando ISession.Get (id). Tengo los siguientes fragmentos XML:NHibernate Eager Obtención de varios niveles
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>
He utilizado el fetch = "unirse" para indicar que atribuir Quiero buscar las entidades hijo para cada padre, y esto ha construido el SQL correcto:
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
Hasta ahora, esto parece bueno - SQL devuelve el conjunto correcto de registros (con solo un orderid distinto), pero cuando ejecuto una prueba para confirmar el número correcto de entidades (desde NH) para pedidos y líneas, obtengo los resultados incorrectos
I debería obtener (de mis datos de prueba), 1xOrder y 4xLine, sin embargo, estoy obteniendo 4xOrder y 4xLine. Parece que NH no reconoce el grupo de "repetición" de información de orden en el conjunto de resultados, ni "reutiliza" correctamente la entidad de orden.
Estoy usando todos los enteros ID (PK), y he intentado implementar IComparable de T y IEquatable de T con este ID, con la esperanza de que NH verá la igualdad de estas entidades. También he intentado descartar Equals y GetHashCode para usar la ID. Ninguno de estos 'intentos' ha tenido éxito.
¿La operación de recuperación de niveles múltiples es compatible con NH y, en caso afirmativo, hay una configuración de XML necesaria (o algún otro mecanismo) para admitirla?
NB: He utilizado la solución de sirocco con algunos cambios en mi propio código para finalmente resolver este. el xml debe cambiarse de una bolsa a otra, para todas las colecciones, y las entidades se cambiaron para implementar IComparable <>, que es un requisito de establecer un conjunto único.
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
...
}
Tenga en cuenta el uso de un campo ID interno. Esto es necesario para entidades nuevas (transitorias); de otro modo, no tendrán inicialmente una ID (mi modelo las ha suministrado cuando se guardaron).
[Esta respuesta] (http://stackoverflow.com/questions/5266180/fighting-cartesian-product-x-join-when-using-nhibernate-3-0-0/5285739#5285739) me ayudó a ver cómo utilizar las consultas QueryOver y Future para buscar con entusiasmo a niños y nietos sin devolver duplicados. La técnica implica dividir la tarea en consultas SQL separadas que se ejecutan en una ida y vuelta a la base de datos. –