2012-06-08 54 views
1

在我的WCF服務的業務邏輯中,我有一個允許按一列或多列過濾用戶的功能。我做了過濾的方法是這樣的:LINQ-To-Entities查詢 - 數據庫上發生了什麼以及本地發生了什麼?

public List<UserDto> GetUsersByFilters (
               String ssn, 
               List<Guid> orderIds, 
               List<MaritalStatusEnum> maritalStatuses, 
               String name, 
               int age 
             ) 
{ 
    using (MyProjEntities entities = new MyProjEntities()) 
    { 
     IQueryable<User> users = entities.Users; 

     // Filter By SSN (check if the user's ssn matches) 
     if (String.IsNullOrEmusy(ssn) == false) 
      users = users.Where(us => us.SSN == ssn); 

     // Filter By Orders (check fi the user has all the orders in the list) 
     if (orderIds != null) 
      users = users.Where(us => UserContainsAllOrders(us, orderIds)); 

     // Filter By Marital Status (check if the user has a marital status that is in the filter list) 
     if (maritalStatuses != null) 
      users = users.Where(pt => maritalStatuses.Contains((MaritalStatusEnum)us.MaritalStatus)); 

     // Filter By Name (check if the user's name matches) 
     if (String.IsNullOrEmusy(name) == false) 
      users = users.Where(us => us.name == name); 

     // Filter By Age (check if the user's age matches) 
     if (age > 0) 
      users = users.Where(us => us.Age == age); 


     return users.ToList(); 
    } 
} 

private Boolean UserContainsAllOrders(User user, List<Guid> orderIds) 
{ 
    return orderIds.All(orderId => user.Orders.Any(order => order.Id == orderId)); 
} 

我的問題是這樣的: 什麼疑問發生在數據庫上,什麼地方發生什麼呢?

很顯然,我並不認爲所有數據庫中的用戶將獲取到我的記憶我認爲,既然「篩選按訂單」使用本地函數每次...

希望 - 不能在數據庫上完成,以便在本地完成。我對嗎 ?

如果是這樣 - 這是否意味着會發生這種情況發生後,當地還,結果一切?

而如果在「篩選按訂單」是不存在?一切都會在數據庫端完成嗎?

是否LINQ-TO-EF知道如何 '翻譯' 的 '婚姻狀況' 查詢數據庫端的查詢? (我正在檢查用戶的婚姻狀況枚舉是否存在於傳遞給函數的枚舉列表中)。

謝謝!

[編輯:對不起。我不知道爲什麼代碼不是自動着色的]

回答

1

如果你將鼠標懸停在不同的「where」語句上,你會發現它們是IQueryable的(或者至少它們應該是).. 。只要你不斷追加Iqueryable「where's」到對方,聲明應該保持爲Iqueryable(而不是每次調用數據庫)。

當你最後在底部做一個ToList時,這就是你實際調用數據庫的時間。

它實際上是非常重要的看着你建立一個LINQ到耳鼻喉科聲明,並確保你不小心調用比你早想返回一個IEnumerable的擴展。如果你不小心調用了一個返回IEnumerable的擴展,然後開始調用「skip」和「take」,試圖執行sql側分頁,那麼你就錯過了......你將跳過並取出內存對象而不是創建優化的SQL查詢。

,究竟發生了什麼事情,它,如果你打開了探查和觀看,當你調用ToList(或任何其他的IEnumerable擴展名)被提交SQL查詢中最有趣的。 Linq to Ent將通常構建一個相當優化的sql語句。添加一個Iqueryable Skip和Take例如,Linq to Ent將爲RowNumber和類似的東西生成必要的sql,以便它可以有效地進行sql server端的分頁。 (請注意,隨着查詢變得越來越複雜,Linq to Ent在創建最優化查詢方面的時間越來越難,如果一個複雜的查詢開始花費太長時間,那麼捕獲被提交的sql是很好的,因爲通常可以編寫自己更優化的在這些情況下查詢)。

您也可以跟蹤sql this way也可以

+0

謝謝Rikon!所以 - 你說的是'Filter By Orders'會拋出一個異常(因爲它是一個試圖在LINQ-TO-ENTITIES查詢上運行的本地函數)?或者它只會導致查詢在本地運行? –

+0

並且您還沒有回答我的其他問題 - LINQ-TO-EF是否知道如何將'婚姻狀態'查詢翻譯成數據庫端查詢? (我正在檢查用戶的婚姻狀況枚舉是否存在於傳遞給函數的枚舉列表中)。 –

+0

新的EF 5知道如何做枚舉...他們是現有EF linq的跟腱。它目前(截至撰寫本文時)處於測試階段,但是如果您可以測試w/beta(並且它不像測試版v1.0),那麼,是的,它會將枚舉轉換爲數據庫中的整數(或任何支持原始類型是)。 – Rikon