2009-06-02 8 views
24

Je veux charger les entités racines et charger avec impatience tous les membres de la collection enfant et de l'agrégat.Désireux de charger la collection enfant avec NHibernate

J'ai essayé d'utiliser le SetFetchMode dans FluentNHibernate, mais je reçois des doublons dans l'une des collections enfant depuis que j'ai une profondeur de 3 niveaux. DistinctRootEntityResultTransformer ne supprime malheureusement que les doublons de racine.

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>(); 

Puis-je utiliser plusieurs requêtes ou quelque chose de similaire pour l'archiver?

De plus, cette approche n'aboutirait-elle pas à des ensembles de résultats inutilement énormes provenant de la base de données?

Des suggestions?

Répondre

0

Bien qu'il ne soit pas exactement ce que vous cherchez, je vous recommande de regarder cet article:

Eager loading aggregate with many child collections

Si vous regardez dans le reste de ce site, vous trouverez encore plus de messages qui traitent chargement impatient et d'autres trucs nHibernate grand.

+2

En effet un bon article, mais pas sûr si je peux l'appliquer à ma situation. La solution décrite dans l'article sur le chargement rapide d'une entité racine spécifique, mon problème est que je veux charger avec impatience une collection d'entités racines. Si je devrais utiliser MultiCritera, je dois trouver un moyen de connecter toutes les différentes requêtes sans spécifier une entité spécifique. Suggestions comment cela peut-il être fait? – Kristoffer

+0

Cet exemple a un seul niveau hiérarchique supplémentaire, mais pas de petits-enfants, pour lesquels MultiQuery/MultiCriteria semble inutile car les requêtes ultérieures ne peuvent pas référencer les résultats des requêtes précédentes (comme Requête # 1: select rootObjects r left join fetch children c où ...; Requête n ° 2: sélectionnez petits-enfants g où parent dans c). –

8

J'ai trouvé une solution mais ce n'est pas joli. Je vais d'abord trouver tous les ID de facture, puis je les utilise dans la requête multiple et ensuite à la fin de filtrer les résultats via un HashedSet. En raison du grand nombre d'éléments parfois je ne pouvais pas utiliser le Restriction.In normalt et a été forcé de l'envoyer comme une chaîne.

Des modifications suggérées?

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>(); 
+0

C'est étrange, les Attestations sont récupérées en tant que requêtes simples. – Kristoffer

+0

+1, C'est en fait (et malheureusement) le meilleur moyen (performance-sage) d'y parvenir. –

+0

Je suis dans une situation similaire (essayant de tirer 3 niveaux à la fois). Bien que votre solution se débarrasse des doublons, elle ne semble avoir que deux niveaux de profondeur. Votre question originale comprenait un troisième niveau appelé "AttestationRequests.Reminders" qui n'est pas inclus dans votre réponse. – MylesRip

2

Pour répondre à votre question: oui, il en résulte d'énormes résultats.

Je suggère à:

  • il suffit d'écrire naïvement vos requêtes sans chargement complet
  • Sur certains endroits, mettre un aggressif, mais une seule par requête
  • si vous avez vraiment des problèmes de performance que vous ne peut pas résoudre avec des index ou en améliorant les requêtes et les stratégies de mappage, utilisez votre solution avec les multiples requêtes.
Questions connexes