2009-08-03 102 views
7

我有一個遞歸的一對多關係,默認的lazy值爲true。我可以針對NH API編寫哪些代碼,以便高效地檢索整個樹,因爲如果我在SubCategories映射上有lazy =「false」?急切加載遞歸關係

這裏的遞歸一個一對多的關係:

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

我不指定爲lazy =因爲懶惰名單上的「假」,需要在大約一半我需要運行查詢。當我設法檢索整個樹時,我在列表上獲取=「subselect」作爲優化。

我已經試過的ICriteria API:

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

但只有即時加載只有在層次結構中的第一級。

回答

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來查找數據庫查詢已完成。

0

不知道是否有幫助,但看一看:map a tree in NHibernate

+0

是的,這是一篇很有用的文章,我已經閱讀過它。幾個月前,當我調查樹木的快速加載時,我發現「熱切的加載祖先和後代」部分是相關的。我的數據庫是SQL Compact,但不支持CTE(分層查詢)。因此編寫一個解決問題的單個查詢看起來是不可能的。 – HappyNomad 2009-08-05 13:54:21

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);