2009-08-03 12 views
7

Ho una relazione ricorsiva uno-a-molti che ha il valore lazy predefinito di true. Quale codice posso scrivere contro l'API di NH che recupererà in modo efficiente l'INTERO albero AS SE ho avuto lazy = "false" nel mapping di sottocategorie?Carattere ricorsivo con carico immediato

Ecco il ricorsiva uno-a-molti:

<class name="Category" lazy="false"> 
    ... 
    <list name="SubCategories" fetch="subselect"> 
      <key column="ParentCategoryID"/> 
      <index column="PositionInList"/> 
      <one-to-many class="Category"/> 
    </list> 

Non specificare pigro = "false" sulla lista poiché la pigrizia è richiesto in circa la metà delle domande che ho bisogno di correre. Ho fetch = "subselect" sulla lista come ottimizzazione per quando riesco a recuperare l'intero albero.

Ho provato l'API ICriteria:

session.CreateCriteria<Category>().SetFetchMode("SubCategories", FetchMode.Eager).Add(Restrictions.IsNull("ParentCategory")).SetResultTransformer(CriteriaSpecification.DistinctRootEntity).List<Category>(); 

ma che solo con entusiasmo caricato solo il primo livello della gerarchia.

risposta

8

Vedere il sito di Ayende: Efficiently Selecting a Tree. Ho usato con successo questa tecnica nelle mie applicazioni. Con ICriteria, sembra che questo:

session.CreateCriteria<Category>() 
    .SetFetchMode("SubCategories", FetchMode.Join) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<Category>() 
    .Where(x => x.ParentCategory == null); 

La principale differenza tra questa versione e che si è tentato è come viene applicato il "== parentCategory null" filtro. Deve essere lasciato fuori dalla query che viene inviata al database per recuperare l'intero albero, ma abbiamo ancora bisogno della query per restituire solo i nodi radice dell'albero, quindi useremo linq per trovare quelli dopo il la query del database è stata completata.

0

Non sono sicuro se aiuta, ma dare un'occhiata a: map a tree in NHibernate

+0

Sì, questo è un articolo utile e l'ho già letto. Quando stavo indagando su un carico veloce di alberi diversi mesi fa, ho trovato rilevante la sezione "Anziani di carico e discendenti". Il mio database è SQL Compact, tuttavia, e non supporta CTE (query gerarchiche). Quindi scrivere una singola query che risolva il problema sembra impossibile. – HappyNomad

1

Ho usato il codice di Daniel come base per risolvere il problema. Ho anche sperimentato con l'equivalente HQL che ho condiviso qui sotto. L'HQL è stato eseguito leggermente più veloce, ma sono andato con ICriteria poiché ho potuto scegliere tra FetchModel.Join e FetchModel.Lazy.

session.CreateQuery("from Category as c left join fetch c.SubCategories") 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<Category>() 
    .Where(c => c.ParentCategory == null); 
Problemi correlati