2011-05-17 136 views
2

我有兩個類:文件,申請人我正在使用ActiveRecord 3.0 RC(NHibernate 3.1.0.4000)。ActiveRecord(NHibernate)渴望加載Bug?

文件

[ActiveRecord("`File`", Lazy = true)] 
public class File : TestProDb<File> { 

    [PrimaryKey("`Id`")] 
    public virtual long Id { get; private set; } 

    [Property("`Name`")] 
    public virtual string Name { get; set; } 

    [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true, Lazy = true)] 
    public virtual IList<Applicant> Applicants { get; set; } 

    public File() { 
     this.Applicants = new List<Applicant>(); 
    } 
} 

申請人

[ActiveRecord("`Applicant`", Lazy = true)] 
public class Applicant : TestProDb<Applicant> { 

    [PrimaryKey("`Id`")] 
    public virtual long Id { get; private set; } 

    [Property("`Surname`")] 
    public virtual string Surname { get; set; } 

    [BelongsTo(Column = "IdFile", Lazy = FetchWhen.OnInvoke)] 
    public virtual File File { get; set; } 
} 

現在我想基於一些申請人規定 - 選擇文件。結果文件應該包含即時加載申請人

using (new SessionScope()) { 
    DetachedCriteria fileQuery = DetachedCriteria.For<File>(); 
    fileQuery.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
    fileQuery.SetFetchMode("Applicants", NHibernate.FetchMode.Eager); 
    fileQuery.CreateCriteria("Applicants").Add(Expression.Like("Surname", "a", MatchMode.Anywhere)); 

    IList<File> files = File.FindAll(fileQuery); 
    foreach (File file in files) { 
     foreach (Applicant applicant in file.Applicants) { 
      Console.WriteLine(applicant.Surname); 
     } 
    } 
} 

從NHProof - 第一查詢時,我執行的FindAll

SELECT this_.[Id]   as Id1_0_1_, 
    this_.[Name]   as Name2_0_1_, 
    applicant1_.[Id]  as Id1_1_0_, 
    applicant1_.[Surname] as Surname2_1_0_, 
    applicant1_.IdFile as IdFile1_0_ 
FROM [File] this_ 
    inner join [Applicant] applicant1_ 
    on this_.[Id] = applicant1_.IdFile 
WHERE applicant1_.[Surname] like '%a%' /* @p0 */ 

從NHProof - 中環Console.WriteLine第二查詢(申請人姓名)

SELECT applicants0_.IdFile as IdFile1_, 
    applicants0_.[Id]  as Id1_1_, 
    applicants0_.[Id]  as Id1_1_0_, 
    applicants0_.[Surname] as Surname2_1_0_, 
    applicants0_.IdFile as IdFile1_0_ 
FROM [Applicant] applicants0_ 
WHERE applicants0_.IdFile = 1 /* @p0 */ 

爲什麼我會爲每個申請人循環(第二個查詢示例)額外往返數據庫?由於FetchMode.Eager,總共只應該有一個數據庫查詢。我完全對此感到困惑。我甚至嘗試刪除虛擬關鍵字,並將所有惰性值設置爲false。還是一樣。這是一個錯誤?

回答

1

您正在獲得額外的請求,因爲對於NHibernate來說,預先加載關聯需要外連接,但是您在查詢中有內連接。爲了解決這個問題,你需要指定:

JoinType.LeftOuterJoin 

I've had similar issue.

編輯

爲什麼NHibernate的需要離開的原因加入如下,考慮下面的代碼:

DetachedCriteria fileQuery = DetachedCriteria.For<File>(); 
fileQuery.SetFetchMode("Applicants", NHibernate.FetchMode.Eager); 

如果NHibernate會在這裏進行內部連接,那麼沒有申請人的文件將不會出現在查詢結果中。這可能不是你所期望的。

但是,當您對申請人姓名創建限制時,您絕對不希望申請人爲空的文件。這允許NHibernate優化查詢一點,但禁用延遲加載。

+0

狡猾,非常感謝你,它現在工作:)我仍然只是不明白爲什麼它使用與LeftOuterJoin別名工作。只是因爲限制? – Cosmo 2011-05-18 09:42:06

+0

不知道我是否正確,但看到我的編輯:) – Sly 2011-05-18 10:17:56

+0

您的解決方案效果很好,我結合Future()使用它,因爲我必須一次加載多個子集合。謝謝! – Cosmo 2011-05-18 11:22:31