2009-06-02 13 views
24

Voglio caricare le entità radice e caricare tutti i dati relativi alla raccolta figlio e ai membri aggregati.Eager caricamento raccolta figli con NHibernate

Ho cercato di utilizzare SetFetchMode in FluentNHibernate, ma sto ottenendo duplicati in una delle raccolte figlio poiché ho una profondità di 3 livelli. DistinctRootEntityResultTransformer sfortunatamente rimuove solo le duplicazioni di root.

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

Posso utilizzare più query o qualcosa di simile per archiviare questo?

Inoltre, questo approccio non comporterebbe inutilmente enormi set di risultati dal database?

Qualche suggerimento?

risposta

0

Anche se potrebbe non essere esattamente quello che stai cercando, mi sento di raccomandare a guardare questo articolo:

Eager loading aggregate with many child collections

Se si guarda intorno il resto di quel sito troverete anche gli altri messaggi che discutono caricamento avido e altre cose fantastiche di ibernazione.

+2

Davvero un buon articolo, ma non so se posso applicarlo alla mia situazione. La soluzione descritta nell'articolo sul caricamento avido di una specifica entità root, il mio problema è che voglio caricare con impazienza una raccolta di entità root. Se dovessi usare MultiCritera ho bisogno di trovare un modo per connettere tutte le diverse query senza specificare un'entità specifica. Suggerimenti su come può essere fatto? – Kristoffer

+0

Questo esempio ha solo un livello di gerarchia aggiuntivo, ma nessun nipote, per il quale MultiQuery/MultiCriteria sembra essere abbastanza inutile, poiché le query successive non possono fare riferimento ai risultati di query precedenti (come Query # 1: selezionare rootObjects r left join recuperare i bambini c dove ...; Query # 2: selezionare i nipoti g dove genitore in c). –

8

Trovato una soluzione ma non è carina. Prima di tutto vado a trovare tutti gli ID fattura, quindi li uso nella multiquery e poi alla fine filtrando i risultati attraverso un HashedSet. A causa dell'elevato numero di elementi, a volte non ero in grado di utilizzare il parametro Normal Restriction.In e sono stato costretto a inviarlo come stringa.

Eventuali modifiche?

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

Ciò è strano, gli attestati vengono recuperati come singole query. – Kristoffer

+0

+1, in realtà (e purtroppo) il modo migliore (prestazioni-saggio) per raggiungere questo obiettivo. –

+0

Sono in una situazione simile (provando a inserire 3 livelli contemporaneamente). Anche se la tua soluzione elimina i duplicati, sembra solo essere profonda 2 livelli. La tua domanda originale includeva un terzo livello down chiamato "AttestationRequests.Reminders" che non è incluso nella risposta. – MylesRip

2

Per rispondere alla tua domanda: sì, risultati in enormi risultati.

Suggerisco a:

  • solo ingenuamente scrivere le vostre domande senza il caricamento diretto
  • In certi luoghi, mettere un ansioso fetch ma solo uno per query
  • se davvero ottiene problemi di prestazioni che si non può risolvere con gli indici o migliorare le query e le strategie di mapping, utilizzare la soluzione con le query multiple.