2012-10-29 99 views
1

對象表達式的Linq返回一個對象,該對象在枚舉時產生序列中的元素。通常,延遲的LINQ-to-Object方法充當流水線,因此序列中的每個元素都會在處理下一個元素之前流經處理管道。對Linq-to-Entities查詢操作的Linq-to-Objects查詢存在一些混淆

一個)但如果LINQ到對象查詢上的LINQ到實體查詢的結果進行操作,那麼當foreach試圖遍歷search,並再次各元件流過整個處理序列的下一個元素被處理之前(換句話說,是從DB檢索的序列中的第一個元素,然後由Enumerable.Where處理,然後由Enumerable.SelectMany處理,然後才從DB檢索下一個元素),或者是一次從DB檢索的整個元素集(當foreach嘗試從序列中讀取第一個元素),只有這些元素開始流經Linq-to-Objects運算符的處理管道?

 var search = context.Contacts.AsEnumerable(). 
      Where(s => s.ContactID > 10).SelectMany(s => s.Address); 

謝謝

回答

1

首先context.Contacts是由表達式轉換(從IQueryable)到SQL的EF查詢供應商處理。

然後,通過AsEnumerable,與EF查詢提供程序的鏈接被破壞,之後的任何內容都是linq到對象,從前面的語句處理結果集。

但是,由於Contact.Address是一個延遲加載的集合,因此每個傳遞管道的Contact都會發出一個新查詢以填充它。這是可能的,因爲EF使用Contact的代理類型,該代理類型通過一個通過EF查詢提供程序運行查詢的getter來覆蓋Address

正如您可能知道的那樣,當您清除AsEnumerable時,整個語句會變成Expression樹,EF將轉換爲一條SQL語句。

+0

1)因此,整個集合一次從DB中檢索,只有Enumerable操作符纔開始處理元素? 2)即使使用這個查詢,Enumerable運算符是否正確,只有當所有的Enumerable運算符完成處理前面的元素時,它纔會開始處理特定的元素? – carewithl

+1

db查詢運行並在'AsEnumerable'之後,任何linq語句鏈被評估爲一個管道。但必須清楚的是,整個語句(包括db部分)只有在實際枚舉時纔會執行。 –

+0

我可以問一下「作爲一條管線」是什麼意思嗎? – carewithl