2009-08-03 8 views
7

Tengo una relación recíproca de uno a muchos que tiene el valor predeterminado de vago verdadero. ¿Qué código puedo escribir contra NH API que recuperará de manera eficiente el árbol TOTAL COMO SI tuviera pereza = "falso" en el mapeo SubCategorías?Cargar con ansiedad la relación recursiva

Aquí está el recursiva relación uno-a-muchos:

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

no especifico lazy = "false" en la lista ya que la pereza se requiere en aproximadamente la mitad de las consultas que tenga que ejecutar. Tengo fetch = "subselect" en la lista como una optimización para cuando consigo recuperar todo el árbol.

He intentado la API ICriteria:

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

pero que sólo ansiosamente cargado sólo el primer nivel de la jerarquía.

Respuesta

8

Véase el sitio de Ayende: Efficiently Selecting a Tree. He utilizado con éxito esta técnica en mis propias aplicaciones. Con ICriteria, que se ve así:

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

La principal diferencia entre esta versión y lo que se pretende es cómo se aplica el "ParentCategory == null" filtro. Tiene que quedar fuera de la consulta que se envía a la base de datos para recuperar todo el árbol, pero todavía necesitamos que la consulta solo devuelva los nodos raíz del árbol, por lo que usaremos linq para encontrarlos después del árbol. consulta de base de datos ha completado.

0

No está seguro si ayuda, pero echa un vistazo a: map a tree in NHibernate

+0

Sí, es un artículo útil y ya lo he leído. Cuando estaba investigando la carga rápida de árboles hace varios meses, encontré relevante la sección "Anhelos y descendientes de carga ansiosa". Mi base de datos es SQL Compact, sin embargo, y no admite CTE (consultas jerárquicas). Entonces, escribir una sola consulta que resuelva el problema parece imposible. – HappyNomad

1

Utilicé el código de Daniel como base para resolver el problema. También experimenté con el HQL equivalente que compartí a continuación. El HQL se ejecutó un poco más rápido, pero fui con ICriteria ya que podía elegir entre FetchModel.Join y FetchModel.Lazy.

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