2011-08-11 58 views
0

有一個關於獲取和預先加載做使用.FetchNHibernate - 查詢後可能獲取集合?

實際查詢時但是,一旦我有一個加載實體SOOO許多文獻 - 用空的集合(因爲我選擇不急於負載在查詢時,由於笛卡爾產品副作用),我可以選擇稍後加載集合,比如在完成一些分頁後,我有一個具體的項目列表?

類似:

var list = (some linq over Session.Query<Entity>) 
.Take(10).Skip(2) 
.Fetch(x => x.MyCollection) 
.ToList(); 

Session.Fetch<Entity>(list, l => l.OtherCollection); 

編輯 的一點是 - 我已經取在查詢2個集 - 使查詢和結果集相當可觀的已經(見NHibernate的笛卡爾乘積)。我想要頁面結果,獲得10的列表,然後可選地返回到數據庫來填充分頁(10,說)結果的子集合屬性。這是性能考慮因素。

回答

1

發出此查詢

/*we dont need the result*/Session.QueryOver<Entity>() 
    .Where(x => x.Id.IsIn(list.Select(l => l.Id))) 
    .Fetch(l => l.OtherCollection) 
    .ToList(); 

然後NHibernate的應該初始化對實體集合

編輯:

,提高初始加載時間看http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate

,那麼你可以爲〔實施例做

var results = (some linq over Session.Query<Entity>) 
    .Take(10).Skip(2) 
    .ToList(); 

var q = Session.QueryOver<Entity>() 
    .Where(x => x.Id.IsIn(list.Select(l => l.Id))) 
    .Fetch(l => l.MyCollection) 
    .ToFuture(); 

Session.QueryOver<Entity>() 
    .Where(x => x.Id.IsIn(list.Select(l => l.Id))) 
    .Fetch(l => l.OtherCollection) 
    .ToFuture(); 

Session.QueryOver<Entity>() 
    .Where(x => x.Id.IsIn(list.Select(l => l.Id))) 
    .Fetch(l => l.ThirdCollection) 
    .ToFuture(); 

return q.ToList() 
+0

是不是隻是急於加載?即時通訊談論如何提取一個斷開的實體或一組斷開連接的實體的集合。 –

+0

@BobTodd不知道你有沒有連接的實體。但它應該是微不足道的重新連接'session.Lock(obj,LockMode.None);'然後執行加載。 sessioncache將確保現有實體將被初始化 – Firo

+0

看起來我們已經在我的答案中找到了同樣的東西(請參閱評論) - 如果原始查詢很昂貴並且您只想執行一次,該怎麼辦?考慮到實際的sql做到這一點,它不會很漂亮,因爲查詢必須看起來像select * from mycollection(id1,id2,id3,id4),但是對於10頁分頁結果,它的性能遠遠好於反覆運行主要查詢 –

0

我剛剛離開去了解NHibernate的期望和預測,看起來很有希望作爲解決方案......當我瞭解它時會發布更多信息。

這是一個解決方案:http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate,但我還是不喜歡它,因爲我的查詢本身是相當昂貴(使用「%樣%@ +分頁),所以執行3次或4次只加載藏品似乎昂貴

編輯

這就是我。注意生成的sql,正在運行正確的sql並返回預期的結果,但返回結果的集合爲null。你能看到缺少什麼嗎?:

public List<Company> CompaniesForLoggedInUser(int pageSize, int pageNumber) 
    { 
     var list = 
     QueryForCompaniesFor(SecurityHelper.LoggedInUsername) 
      .Page(pageNumber, pageSize) 
      .ToList() 
      .FetchCompanyCollections(Session); 
     return list; 
    } 

internal static class CompanyListExtensions 
    { 
    internal static List<Company> FetchCompanyCollections(this List<Company> companies, ISession session) 
    { 
     var ids = companies.Select(l => l.Id).ToArray(); 

     session.QueryOver<Company>() 
     .Where(x => x.Id.IsIn(ids)) 
     .Fetch(l => l.Properties).Eager() 
     .Future(); 

     return session.QueryOver<Company>() 
     .Where(x => x.Id.IsIn(ids)) 
     .Fetch(l => l.UserAccessList).Eager() 
     .Future() 
     .ToList(); 
    } 
    } 
+0

對我來說看起來不錯,但你可以嘗試'session.QueryOver () 。其中(x => x.Id.IsIn(ids)) .Fetch(l => l.UserAccessList)。Eager() .Future() .ToList();返回公司;' – Firo

+0

我的概率是第二次未來不是第一次,你的原始答案是現貨(但錯過了ToList) –