2012-08-25 63 views
2

假設我們有以下LINQ查詢:什麼時候實際執行LINQ查詢?

var query = 
    from c in Customers 
    where c.Country == "Italy" 
    orderby c.Name 
    select new { c.Name, c.City }; 

編譯器將其轉換是這樣的:

IEnumerable<Customer> query = 
     Customers 
     .Where(c => c.Country == "Italy"); 
     .OrderBy(c => c.Name) 
     .Select(c => new { c.Name, c.City }); 

然後我coud使用這樣的查詢:

foreach (var name_city_pair in query) ... 

的問題是:

  • 當我使用foreach循環時,似乎查詢指定的數據已被查詢出 。那麼這個查詢操作什麼時候發生? 是什麼時候我定義了LINQ查詢對象IEnumerable<Customer>

  • 如果數據數量過大,有沒有後期查詢 機制? (我不知道正確的詞來形容這一點,但 我希望你讓我。)

+0

我想你可能有上面的一些語法錯誤。您正在選擇匿名類型,然後說所選對象的類型爲Customer,然後遍歷查詢,如IEnumerable 。 – vossad01

+0

感謝您的提醒。現在更正。 – smwikipedia

回答

5

LINQ使用延遲執行在可能的情況。在你的例子中,查詢只在迭代結果時執行。

To(例如ToList)開頭的方法會立即執行查詢。另外一些返回單個值的方法(如Count)會導致查詢立即執行。

1

查詢不會在foreach之前執行。 foreach循環中的每次迭代都會從查詢中返回一個結果。

從來沒有完全物化的數據結果集,所以它也不能太大。

LINQ查詢延遲執行。在迭代時,它將使用您指定的謂詞和投影向前「滑動」數據。

3

一般來說,LINQ會盡可能地使用懶惰。例如,你希望它看起來像這樣的幕後:

foreach (string name in query) ... 
//Roughly translates into 
while (query.MoveNext()) 
{ 
    string name = query.Current; 
    ... 
} 

其中僅得到的結果,因爲它需要他們,一個接一個。這種'懶惰'/'流'思想貫穿於整個查詢中 - 根據需要選擇調用OrderBy,根據需要調用Where根據需要調用Collection。

奇怪的是'OrderBy',由於實現的原因,它可能在排序前檢索所有需要的結果,然後流式傳輸結果。這個檢索將在第一次調用時發生。

+0

這是否假定Linq-To-Objects?如果是這樣,如果它是Linq-To-Sql或Entity Framework,你的答案會有什麼不同? –

+0

具體細節假定LinqToObjects,儘管所有的實現都應該嘗試懶惰IIRC。例如,MongoDB會在第一次調用時編譯並向數據庫發送查詢,並返回一個'MongoCursor',它將處理爲每次迭代IIRC獲取文檔。 [它可以批量文件4MB一次IIRC]。 – NPSF3000

相關問題