Deseosos de cargar la colección infantil con NHibernate.
eager-loading querying (3)
Quiero cargar entidades raíz y cargar con entusiasmo toda su colección secundaria y miembros agregados.
He estado tratando de usar SetFetchMode
en FluentNHibernate, pero estoy obteniendo duplicados en una de las colecciones secundarias ya que tengo una profundidad de 3 niveles. DistinctRootEntityResultTransformer
desafortunadamente solo elimina las duplicaciones de raíz.
return Session.CreateInvoiceBaseCriteria(query, archived)
.AddOrder(new Order(query.Order, query.OrderType == OrderType.ASC))
.SetFetchMode("States", FetchMode.Eager)
.SetFetchMode("Attestations", FetchMode.Eager)
.SetFetchMode("AttestationRequests", FetchMode.Eager)
.SetFetchMode("AttestationRequests.Reminders", FetchMode.Eager)
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List<Invoice>();
¿Puedo usar consultas múltiples o algo similar para archivar esto?
Además, ¿este enfoque no resultaría en conjuntos de resultados innecesariamente grandes de la base de datos?
¿Alguna sugerencia?
Encontré una solución pero no es bonita. Primero voy y encuentro todas las ID de facturas, luego las uso en el multiquery y luego al final filtrando los resultados a través de un HashedSet. Debido a la gran cantidad de elementos, a veces no podía usar el Restricción normal y era forzado a enviarlo como una cadena.
¿Alguna sugerencia sugerida?
var criteria = Session.CreateInvoiceBaseCriteria(query, archived)
.SetProjection(Projections.Id());
var invoiceIds = criteria.List<int>();
if (invoiceIds.Count > 0)
{
var joinedIds = JoinIDs(criteria.List<int>()); // To many ids to send them as parameters.
var sql1 = string.Format("from Invoice i inner join fetch i.States where i.InvoiceID in ({0}) order by i.{1} {2}", joinedIds, query.Order, query.OrderType.ToString());
var sql2 = string.Format("from Invoice i inner join fetch i.AttestationRequests where i.InvoiceID in ({0})", joinedIds);
var sql3 = string.Format("from Invoice i inner join fetch i.Attestations where i.InvoiceID in ({0})", joinedIds);
var invoiceQuery = Session.CreateMultiQuery()
.Add(sql1)
.Add(sql2)
.Add(sql3);
var result = invoiceQuery.List()[0];
return new UniqueFilter<Invoice>((ICollection)result);
}
return new List<Invoice>();
Para responder a su pregunta: sí, da lugar a enormes conjuntos de resultados.
Sugiero a
- simplemente ingenuamente escriba sus consultas sin ansias de obtener
- En ciertos lugares, ponga una búsqueda ansiosa, pero solo una por consulta
- Si realmente tiene problemas de rendimiento que no puede resolver con índices o mejorando las consultas y las estrategias de mapeo, use su solución con las múltiples consultas.
Si bien puede que no sea exactamente lo que estás buscando, te recomendaría que consultes este artículo:
Agregado de carga ansioso con muchas colecciones secundarias
Si miras alrededor del resto de ese sitio, encontrarás aún más publicaciones que discuten sobre la carga ansiosa y otras grandes cosas de NHibernate.