2013-10-15 40 views
18

子句在LINQ到實體您可以通過查詢實體:表現爲使用2,其中在LINQ

var students = SchoolContext.Students.Where(s => s.Name == "Foo" && s.Id == 1); 

我知道在幕後將被轉換爲SQL語句類似於:

SELECT * 
FROM Students 
WHERE Name = 'Foo' AND Id = 1 

但是是有區別(相對於性能),如果我寫:

var students = SchoolContext.Students 
          .Where(s => s.Name == "Foo") 
          .Where(s => s.Id == 1); 

將它翻譯到相同的SQL查詢?根據我的理解,.Where()將返回IEnumerable<T>,因此第二個.Where()將過濾內存中的實體,而不是將IQueryable<T>轉換爲SQL,這是否正確?

回答

18

第一個.Where()子句仍將返回IQueryable<T>。只要您是在IQueryable<T>操作將繼續建立SQL查詢並執行它時,收集需要被帶入存儲器(例如:在foreach環或ToList()操作使用時,作爲@anaximander指出

因此:

SchoolContext.Students.Where(s => s.Name == "Foo").Where(s => s.Id == 1); 

還有翻譯成:

SELECT * 
FROM Students 
WHERE Name = 'Foo' AND Id = 1 

雖然低於2語句會轉化爲相同的查詢:

SchoolContext.Students.Where(s => s.Name == "Foo").Where(s => s.Id == 1); 
SchoolContext.Students.Where(s => s.Name == "Foo" && s.Id == 1); 
+4

即使不使用分析器也可以調試此方法的一個好方法是斷開代碼並將鼠標懸停在Visual Studio中的變量上,這種方式通常會用來查看某個值的方式。它會在展開時顯示生成的SQL。 – NibblyPig

+3

@SLC:請注意,您所說的只有在使用現代實體框架的'DbContext' API和相關的'DbQuery'時纔有效。如果他使用ObjectContext和相關的ObjectQuery,則需要調用ToTraceString來代替。 (原因:DbQuery的'ToString'實現調用'ObjectQuery.ToTraceString')。 –

+0

很高興知道,謝謝! – NibblyPig

7

首先在哪裏返回IQueryable<T>所以不會有性能差異。

2

不,它將是相同的查詢。

您可以撰寫一個越來越複雜的查詢由fluently鏈接IQueryable由每個Linq操作返回。該語句不會生成併發送到服務器,直到您評估結果。

您可以檢查通過調試生成的實際查詢並將鼠標懸停在查詢or doing a ToTraceString()上,或使用SQLProfiler之類的工具監視數據庫服務器。

1

兩者應該產生相同的SQL; IQueryable是聰明的,因爲它直到需要時才進行實際評估。只要您使用.ToList().Count()foreach或任何需要知道什麼是IQueryable,它會生成SQL,查詢數據庫,並給你結果的第二.Where()應添加到第一個,然後。

1

獲取Linqpad,然後嘗試不同的查詢。您可以直接向實體添加連接,運行查詢並查看每種情況下生成的SQL。與Linq一起試驗的絕佳方式。