1

如何在不實際執行查詢的情況下延遲加載嵌套列表?使用非常簡單的例子,說我有:Linq2Sql - 你如何延遲加載嵌套列表?

class CityBlock { 
    IList<Building> BuildingsOnBlock; 
    Person BlockOwner; 
} 

class Building { 
    IList<Floor> FloorsInBuilding; 
} 

class Floor { 
    IList<Cubicle> EmployeeCubicles; 
} 

Class Cubicle { 
    System.Guid CubicleID; 
    Person CubicleOccupant; 
} 

然後在我的倉庫層,我有以下方法:

GetCityBlocks() 

然後在服務層我要GetCityBlocksByOwner,其中我使用的擴展方法來獲得特定的人所擁有的城市街區,說我們只想圭多的塊:

GetCityBlocks().ForOwner("Guido") 

如果我們做一個.ToList()在倉庫中它要執行查詢 - 這將是荒謬的,因爲我們不知道我們在那個級別獲得的塊是誰。所以問題是,我們如何有效地做到這一點?

假設有50000個街區所有者和100萬個城市街區,加載它們不是一個選項。使用IQueryables將無法工作,因爲嵌套(沒有極端黑客攻擊,至少我知道)。此外,如果我嘗試使用Rob Conery的LazyList之類的東西,那麼我們基本上會從我們的DAL泄漏到我們的域模型中,這可能在未來非常糟糕。

那麼我該如何正確地做到這一點?

  • 難道是確定 正確的上下文嗎?如果是這樣,我們會在存儲庫層還是 服務層執行 ?
  • 我是否將服務層和我的存儲庫層合併在一起,以獲得非常具體的服務方法 ?
  • 或者我完全錯過了一些東西? (還是相對較新的LINQ2SQL 的事情,這將被淘汰 反正所以...)

編輯: 在存儲庫模式,我們目前映射到我們的域對象,所以它會是這個樣子:

public IQueryable<CityBlock> GetCityBlocks(){ 
    var results = from o in db.city_blocks 
        let buildings = GetBuildingsOnBlock(o.block_id) 
        select new CityBlock { 
         BuildingsOnBlock = buildings, 
         BlockOwner = o.block_owner 
        }; 
    return results; 
} 

對於這項工作,我們不得不使建築得到.ToList(),除非我們做的是,在實際CityBlock Field對象爲IQueryable - 這不看起來是正確的,因爲看起來任何訪問Cit的人都有太多的權力yBlock.BuildingsOnBlock字段。這是映射到我們的域對象的東西,我們應該可能做的服務層?

+0

整體淘汰的是一個紅色的鯡魚上。誠然,它不會在改進方面得到太多關注,但它已經在框架中,所以它會與我們在一段時間。無論如何,StackOverflow使用Linq to SQL,我會說它工作得很好。 – 2009-08-13 23:49:03

+0

你從GetCityBlocks()方法返回什麼?既然你使用擴展過濾器,我猜你已經返回IQueryable了嗎?否則你真的應該使用羅伯特的答案。請注意,從存儲庫中公開IQueryable意味着只公開Linq而不是Linq2Sql – Jaime 2009-08-14 00:09:58

回答

1

您可以通過返回IQueryables而不是ILists來完成。

ToList()會立即執行查詢,因爲轉換必須從IQueryable執行到IList。

只要您返回IQueryables,延遲加載應推遲執行,直到實際需要數據,即調用ToList()時爲止。

目前我找不到引用,但我的理解是,如果你這樣做,linq to sql有機會優化它發送給服務器的SQL。換句話說,它最終將讀取這些記錄:

GetCityBlocks().ForOwner("Guido") 

,而不是這些記錄:

GetCityBlocks() 
+0

但是,在域模型中使用IQueryable看起來像是一個問題,因爲您只是爲DAL執行而這樣做,而不是因爲它是該域的一部分模型。 IQueryable不一定是查詢該對象中的那些字段/屬性/類對象所需的東西。還是我仍然不正確地看待這個問題? – MunkiPhD 2009-08-13 23:57:46

+0

我同意你放鬆控制的一點,但如果我們映射到我們自己的對象在存儲庫中呢?這是我們應該在別處做什麼的嗎? (請參閱我的編輯) – MunkiPhD 2009-08-14 00:14:40

0

你可以嘗試不同的方法,映射你的域對象,使其工作。問題是,不管你做什麼(除非你在你的域對象中將你的列表更改爲IQueryables),你將在映射時結束ToList()。

讓linq2Sql通過創建自定義數據環境並且不使用設計器進行映射的方式來映射到您的POCO的另一種方式:),這樣您可以保持域模型清潔並讓linq2Sql在正確的位置填充依賴關係時間。請注意,進入此路線有其自身的問題,但可以完成。

這裏有一個鏈接,讓你開始這條路線

Achieving POCO s in Linq to SQL