Tengo este gráfico de objetos:LINQ to NHibernate ThenFetch múltiples propiedades
// Lots of stuff omitted for brevity; these are all virtual properties and there
// are other properties which aren't shown on all classes.
class A {
B b;
C c;
DateTime timestamp;
}
class B {
X x;
Y y;
}
class X {
int id;
}
class C { }
class Y { }
or to put it more simply,
a = {
b: {
x { id: int },
y: { }
},
c: { },
timestamp: DateTime
}
Ahora estoy haciendo una consulta a dónde voy a devolver una lista de A
s y necesito todos sus B
s , C
s, X
sy Y
s. También voy a agruparlos por B en una búsqueda.
ILookup<B, A> GetData(List<int> ids) {
using (ISession session = OpenSession()) {
var query = from a in session.Query<A>()
where ids.Contains(a.b.x.id)
orderby A.timestamp descending
select a;
query = query
.Fetch(a => a.b)
.ThenFetch(b => b.x)
.Fetch(a => a.b)
.ThenFetch(b => b.y)
.Fetch(a => a.c);
return query.ToLookup(a => a.b);
}
}
Un par de cosas a tener en cuenta:
- Este es un informe donde todos los datos tiene que ser devuelto - Resultados sin límites no es un problema.
- Estoy haciendo la agrupación usando
ToLookup
porque el uso degroup by
parece ser más complicado cuando necesita todos los valores reales, necesita consultar la base de datos para los grupos y luego sus valores reales.
Mi pregunta es cómo especificar la estrategia de búsqueda correctamente. La forma en que he hecho es la única manera que encontré para esto para ejecutar (con exagerado todo el BX y por los valores) - pero produce SQL que parece equivocada:
select /* snipped - every mapped field from a0, b1, x2, b3, y4, c5 - but not b6 */
from [A] a0
left outer join [B] b1
on a0.B_id = b1.BId
left outer join [X] x2
on b1.X_id = x2.XId
left outer join [B] b3
on a0.B_id = b3.BId
left outer join [Y] y4
on b3.Y_id = y4.YId
left outer join [C] c5
on a0.C_id = c5.CId,
[B] b6
where a0.B_id = b6.BId
and (b6.X_id in (1, 2, 3, 4, 5))
order by a0.timestamp desc
Como se puede ver que se está haciendo el valor de a.b
3 veces - b1
y b3
para la recuperación, y b6
para la cláusula where.
- Supongo que esto tiene un impacto negativo en el rendimiento de la base de datos. ¿Estoy en lo correcto?
- ¿Hay alguna forma de modificar mis llamadas
.Fetch
para que solo obtengaa.b
una vez? - ¿Este es un buen enfoque para mi problema?
En primer lugar, estos son todos muchos como se puede ver en el mapeo (solo hay un B en una A, y no una lista de ellos), por lo que toda la consulta solo cargará 4 entidades. En segundo lugar, lo que está sugiriendo es exactamente lo contrario de lo que yo quisiera: en lugar de reducir la complejidad de la consulta, la ha aumentado dividiéndola en varias consultas. La consulta ideal tendrá las siguientes combinaciones: 'desde [A] unión externa izquierda [B] en ...left outer join [X] en ... left outer join [Y] on ... '. – configurator
Mi comentario anterior suena duro; No quise disuadirte de tratar de ayudar. Agradezco tu esfuerzo, incluso si no parece ser el resultado de mi comentario anterior. – configurator
He comprobado el comportamiento sugerido sobre la precarga de entidades relacionadas. Utilizando NHibernate Profiler puedo ver que solo se obtienen una vez, por lo que puede confirmar que lo que dice bdrajer es cierto sobre el almacenamiento en caché de los datos en la sesión. –