急切加载递归关系

时间:2009-08-03 16:01:51

标签: nhibernate

我有一个递归的一对多关系,其默认延迟值为true。如果我在SubCategories映射上有lazy =“false”,我可以用NH API编写哪些代码来有效地检索整个树?

这是递归的一对多关系:

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

我没有在列表中指定lazy =“false”,因为在我需要运行的大约一半查询中需要懒惰。我在列表上有fetch =“subselect”作为我在设法检索整个树时的优化。

我已经尝试过ICriteria API:

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

但只是急切地只加载了层次结构中的第一个级别。

3 个答案:

答案 0 :(得分:8)

见Ayende的网站:Efficiently Selecting a Tree。我在自己的应用程序中成功使用了这种技术。使用ICriteria,它看起来像这样:

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

此版本与您尝试的内容之间的主要区别在于如何应用“ParentCategory == null”过滤器。它必须被排除在发送到数据库的查询之外才能检索整个树 - 但我们仍然需要查询只返回树的根节点,所以我们将使用linq来查找数据库查询已经完成。

答案 1 :(得分:1)

我使用Daniel的代码作为解决问题的基础。我还尝试了下面分享的等效HQL。 HQL的执行速度稍快,但我选择了ICriteria,因为我可以在FetchModel.Join和FetchModel.Lazy之间进行选择。

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

答案 2 :(得分:0)

不确定是否有帮助但请查看:map a tree in NHibernate