2015-09-06 40 views
1

我有一個web應用程序,並且我正在使用實體框架連接到一個數據庫。在什麼時候需要將查詢的工作卸載到數據庫?

要選擇所有Employee記錄某一個部門的,例如,我可以很容易地寫:

....Employees.Where(o => o.Department == "HR").ToList();

工作正常。但它是最優的?

這個Where子句應該被合併到存儲過程或視圖中嗎?或者,我的實體框架代碼是否可以完成將其轉換爲SQL的工作?

過去從我們團隊中發現性能問題時,人們會將記錄拉入內存,然後在.net而不是數據庫級別執行篩選。我試圖避免這種情況再次發生,所以想要清楚我必須避免的事情。

回答

1

如果Employees由實體框架提供,那麼Where()將被翻譯成SQL併發送到數據庫。只有這樣,您才能實現對象,而不必將之前應用的過濾器轉換爲SQL。在那之後的任何事情只是簡單的LINQ到對象。

導致物化發生的方法包括諸如.ToList().ToArray()(還有更多,但這兩個可能是最常見的)。

如果您想查看SQL Server上正在發生的事情,應該打開SQL事件探查器並查看正在發送的查詢。

1

從過去人們將記錄拉入內存然後在.net而不是在數據庫級進行過濾的過去,我們在過去的團隊中遇到過性能問題。

只是作爲附錄科林的回答,並針對上面的報價,以避免這種情況的辦法是,以確保您的數據庫查詢與IQueryable<T>第一個完全構建,通過調用枚舉結果之前如.ToList() ,或.ToArray()

作爲一個例子,考慮以下:

IEnumerable<Employee> employees = context.Employees; 
// other code, before executing the following 
var hrEmployees = employees.Where(o => o.Department == "HR").ToList(); 

.ToList()將枚舉結果斂從上下文員工首先,和然後執行在客戶端上的過濾。如果你有很多員工需要應對,這個表現不會很好,而且這個規模肯定不會很好。

相比之下,與此:

IQueryable<Employee> employees = context.Employees; 
// other code, before executing the following 
var hrEmployees = employees.Where(o => o.Department == "HR").ToList(); 

IQueryable<T>IEnumerable<T>派生。它們之間的區別在於IQueryable<T>內置了查詢提供程序,並且您構建的查詢被表示爲表達式樹。這意味着只有在枚舉查詢結果的調用(例如.ToList())之後纔會對其進行評估。

在上面的第二個示例中,查詢提供程序將執行SQL以僅提取屬於HR部門的員工,對數據庫本身執行過濾。

相關問題