2009-01-24 75 views
2

我有一個表父和一個表子。 Child包含Parent表的外鍵,從而創建一對多關係。這裏是我的映射的一部分,我用流利的NHibernate的定義:NHibernate:無法成功設置延遲加載

public class ParentMap : ClassMap<Parent> 
{ 
    public ParentMap() 
    { 
     WithTable("Parents"); 

     Id(x => x.Id, "ParentID") 
     .WithUnsavedValue(0) 
     .GeneratedBy.Identity(); 

     Map(x => x.Description, "Description"); 

     HasMany<Child>(x => x.Childs) 
     .LazyLoad() 
     .WithKeyColumn("ParentID") 
     .IsInverse() 
     .AsSet(); 
    } 
} 

public class ChildMap : ClassMap<Child> 
{ 
    public ChildMap() 
    { 
     WithTable("Childs"); 

     Id(x => x.Id, "ChildID") 
     .WithUnsavedValue(0) 
     .GeneratedBy.Identity(); 

     References(x => x.Parent, "ParentID") 
      .CanNotBeNull() 
      .LazyLoad(); 
    } 
} 

正如你可以看到我已經設置LazyLoad上的關係。還要注意,在我的模型類中,所有屬性都設置爲虛擬。

現在的簡單查詢:

ICriteria crit = Session.CreateCriteria(typeof(Child)) 
    .Add(Expression.Eq("Id", 18)); 
IList<Child> list = crit.List<Child>(); 

和SQL生成:

SELECT this_.ChildID   as ChildID5_1_, 
     this_.ParentID   as ParentID5_1_, 
     parent2_.ParentID as ParentID4_0_, 
     parent2_.Description as Descript2_4_0_ 
FROM Childs this_ 
     inner join Parents parent2_ 
     on this_.ParentID = parent2_.ParentID 
WHERE this_.ChildID = 18 /* @p0 */ 

正如你所看到的,它做了一個連接的父表,並選擇其字段(ID和說明)。但爲什麼它會這樣做,因爲我要求lazyloading?現在

如果我更改查詢到:

ICriteria crit2 = Session.CreateCriteria(typeof(Child)) 
    .SetFetchMode("Parent", FetchMode.Lazy) 
    .Add(Expression.Eq("Id", 18)); 

有產生2個SQL查詢:

SELECT this_.ChildID as ChildID5_0_, 
     this_.ParentID as ParentID5_0_ 
FROM Childs this_ 
WHERE this_.ChildID = 18 /* @p0 */ 

這是很好的對我說:不加入,父表中沒有查詢。 但我得到這個第二個太:

SELECT parent0_.ParentID as ParentID4_0_, 
     parent0_.Description as Descript2_4_0_ 
FROM Parents parent0_ 
WHERE parent0_.ParentID = 45 /* @p0 */ 

再次查詢父表。

這2個查詢行過程中產生的:

IList<Child> list = crit.List<Child>(); 

我一無所知的東西在這裏發生。有人可以幫忙嗎?

回答

6

這取決於你的版本的流利NHibernate。直到某個點,默認情況下,所有實體將不是被延遲加載。這相當於在您的實體中明確設置lazy="false"。這不再是這種情況,但如果你在這之前運行任何事情,那麼你會看到這種行爲。

多對一/引用延遲加載設置被來自目標的實體級懶惰加載覆蓋,所以如果您在此舊版本的FNH上運行,則實體設置將呈現References(...).LazyLoad()調用模擬。

您需要驗證您使用的是最新版本的FNH,它應該能夠解決問題;然而,如果它不是,那麼你需要在你的Parent實體中明確地設置延遲加載。您可以使用ClassMap<T>上的LazyLoad方法來完成此操作。