2010-09-07 5 views
5

Das ist keine Frage als solche, ich habe dieses Thema in den letzten paar Tagen recherchiert und dachte, dass ich etwas beitragen möchte, das viele der disparaten Ideen einbrachte, die ich ' Ich habe gelesen und meine Lösung für das Problem vorgeschlagen ...Eifriges Laden von Baum/Hierarchien mit Nhibernate

Das Problem ist eifrig Laden von n Ebene Kind Objekte innerhalb Nhibernate und das nHibernate wird nicht wissen, die Tiefe des Baumes. Ich habe gesehen, dass dies mit der Verwendung von straight sql und Union All gelöst wurde, aber leider konnte ich das nicht zur Arbeit bringen, normalerweise weil nhibernate nicht weiß, dass Sie die Objekte eifrig geladen haben. So sah ich den folgenden Code für eifrigen Laden ein Objekt Kriterium

 var children = Session.CreateCriteria<MenuNode>() 
      .SetFetchMode("Children", FetchMode.Eager) 
      .Add(Expression.Eq("Id", 1)) 
      .List<MenuNode>(); 

Dies wird eifrig Last des Kind für Id 1, von hier aus der In-Anweisung eifrig Last mehr Objekte auf einmal verwenden kann. Also muss ich nur alle Knoten-IDs ausarbeiten, die zu dieser Hierarchie gehören und diese mit der In-Anweisung laden.

Also, wenn ich eine übergeordnete Tabelle der Hierarchie und jeder Knoten hat eine Hierarchie-ID, dann kann ich für diese Hierarchie eine Liste aller Knoten-IDs erhalten mit dieser hql

var sql = "select Distinct id from Nodes where (HierarchyId = :id) "; 
var ids = Session.CreateSQLQuery(sql) 
      .SetInt32("id", id) 
      .List(); 

und von hier eifrig Last allein alle Kinder für diesen Baum

var children = Session.CreateCriteria<MenuNode>() 
      .SetFetchMode("Children", FetchMode.Eager) 
      .Add(Expression.In("Id", ids)) 
      .List<MenuNode>(); 

Das einzige Problem dabei ist, dass Sie nicht gerne haben die erste Ebene Pegel der Knoten aus der Hierarchie übergeordneten Tabelle geladen, die normalerweise getan werden kann ..

var menu = Session.CreateCriteria<Menu>() 
      .SetFetchMode("RootNodes", FetchMode.Eager) 
      .Add(Expression.Eq("Id", id)) 
      .List<Menu>(); 

Also das ist es, in drei SQL-Anweisungen haben Sie eifrig ein untergeordnetes Objekt auf n Ebenen geladen. Um noch weiter zu optimieren, habe ich mehrere Queries verwendet, um die beiden Hauptabfragen miteinander zu verbinden und beide Anweisungen gleichzeitig zu senden. Die Anweisung, die IDs zurückzuziehen, müssen unabhängig ausgeführt werden, um die IDs zurückzuziehen.

Weitere Einzelheiten mehrkriteriellen zu eifrig Last verwendet, können hier gefunden ..

http://nhforge.org/blogs/nhibernate/archive/2008/09/06/eager-loading-aggregate-with-many-child-collections.aspx

Hope Dieses etwas Hilfe zu jemandem

Antwort

2

Ich weiß, dass Sie nicht eine Frage zu stellen, sondern Ich dachte, ich würde teilen, wie ich es vorziehe. Siehe http://ayende.com/Blog/archive/2009/08/28/nhibernate-tips-amp-tricks-efficiently-selecting-a-tree.aspx

return session.CreateCriteria<MenuNode>() 
    .SetFetchMode("Children", FetchMode.Join) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<MenuNode>(); 

Ich weiß nicht, ob dies alles erreicht, die Sie mit Ihrem Ansatz zu erreichen beabsichtigt, aber ich habe festgestellt, es ist ein sehr nützliches Werkzeug sein, wenn mit hierarchischen Daten handelt.