2010-09-07 16 views
5

Esto no es una pregunta como tal, he estado investigando este tema durante los últimos días y pensé que me gustaría contribuir con algo que generó muchas de las ideas dispares que yo ' He estado leyendo y presenté mi solución al problema ...Deseosa carga de árbol/jerarquías usando Nhibernate

El problema es la carga ansiosa de n niveles de objetos secundarios dentro de Nhibernate y que nHibernate no conocerá la profundidad del árbol. He visto esto resuelto usando SQL directo y Union All, pero desafortunadamente no pude conseguir que funcionase, generalmente porque nhibernate no sabe que has ansiado cargar los objetos. Así que miré el siguiente código para la carga ansiosa un objeto utilizando el criterio

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

Esta carga ansiosos hará al niño para ID 1, desde aquí se puede utilizar la instrucción para múltiples entidades de carga ansiosa a la vez. Así que solo necesito calcular todos los identificadores de nodo que pertenecen a esta jerarquía y cargarlos con la instrucción In.

Así que si puedo crear una tabla primaria a la jerarquía y cada nodo tiene un identificador de jerarquía entonces puedo obtener una lista de todos los nodos de identificación para esta jerarquía usar este HQL

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

y desde aquí la carga ansiosa todos los niños de este árbol solo usando

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

el único problema con esto es que usted no tiene ganas cargado los primeros niveles a nivel de los nodos de la tabla primaria jerarquía, lo cual puede hacerse normalmente ..

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

Eso es todo, en tres sentencias de SQL tiene ansioso cargar un objeto secundario a n niveles. Para optimizar aún más he utilizado la consulta múltiple para vincular las dos consultas principales y enviar ambas declaraciones al mismo tiempo. Sin embargo, la declaración para retirar la necesidad de la identificación de ejecutarse de forma independiente para retirar la identificación.

Más detalles de la utilización de multicriterio a la carga con ganas se pueden encontrar aquí ..

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

Esperanza esta de alguna ayuda para alguien

Respuesta

2

Soy consciente de que usted no está haciendo una pregunta, pero Pensé que compartiría la forma en que prefiero hacer esto. Veo 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>(); 

No sé si esto logra todo lo que la intención de lograr con su enfoque, pero he encontrado que es una herramienta muy útil cuando se trata de datos jerárquicos.

Cuestiones relacionadas