2012-01-09 135 views
52

我有一個LINQ查詢,看起來像下面這樣:與LINQ擴展方法多WHERE子句

DateTime today = DateTime.UtcNow; 
var results = from order in context.Orders 
       where ((order.OrderDate <= today) && (today <= order.OrderDate)) 
       select order; 

我想學習/瞭解LINQ。在某些情況下,我需要添加兩個額外的WHERE子句。在努力做到這一點,我使用的是:

if (useAdditionalClauses) 
{ 
    results = results.Where(o => o.OrderStatus == OrderStatus.Open) // Now I'm stuck. 
} 

正如你所看到的,我知道如何添加一個額外的WHERE子句。但是,我如何添加多個?舉例來說,我想

WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID

添加到我以前的查詢。我如何使用擴展方法來做到這一點?

謝謝!

回答

101

兩種方式:

results = results.Where(o => (o.OrderStatus == OrderStatus.Open) && 
          (o.CustomerID == customerID)); 

或:

results = results.Where(o => (o.OrderStatus == OrderStatus.Open)) 
       .Where(o => (o.CustomerID == customerID)); 

我通常更喜歡後者。但值得剖析SQL服務器來檢查查詢執行情況並查看哪一個對您的數據更好(如果有任何差異的話)。

關於鏈接.Where()方法的注意事項:您可以鏈接所有您想要的LINQ方法。像.Where()這樣的方法實際上並沒有針對數據庫執行(還)。他們defer execution直到計算出實際結果(例如用.Count().ToList())。所以,當你把多種方法連接在一起(更多的呼叫到.Where(),或許是.OrderBy()或其他的東西等等),他們建立了所謂的expression tree。當整個樹需要評估時,它就是針對數據源執行的。

+0

我覺得不知道我可以做到這一點..你剛剛從我這麼多意大利麪代碼中救了我。 – ledgeJumper 2014-02-21 00:58:47

+0

謝謝,這幫助了我。但是,也有可能我會根據某個變量觸發where子句中的任何一個? @David – 2015-09-21 13:17:34

0

只需使用&&運算符就像使用任何其他需要執行布爾邏輯的語句一樣。

if (useAdditionalClauses) 
{ 
    results = results.Where(
        o => o.OrderStatus == OrderStatus.Open 
        && o.CustomerID == customerID)  
} 
3

肯定:

if (useAdditionalClauses) 
{ 
    results = 
    results.Where(o => o.OrderStatus == OrderStatus.Open && 
    o.CustomerID == customerID) 
} 

,還是一種.Where()調用像這樣的(雖然我不知道你爲什麼會想,除非它被另一個布爾控制變量拆分):

if (useAdditionalClauses) 
{ 
    results = results.Where(o => o.OrderStatus == OrderStatus.Open). 
    Where(o => o.CustomerID == customerID); 
} 

或者另一個重新分配到results:`results = results.Where(blah)。

14

您可以繼續像他們一樣鏈接它們。

results = results.Where (o => o.OrderStatus == OrderStatus.Open); 
results = results.Where (o => o.InvoicePaid); 

這代表AND。

+0

你 - 和其他人 - 也打敗了我,但這可能是最可讀的方式。 – 2012-01-09 16:22:21

+4

重複將where子句添加到查詢中,並在兩者之間使用「和」運算符。 – linkerro 2012-01-09 16:25:16

+0

這可能不是'最乾淨'的解決方案,但在我的情況下,這是迄今爲止唯一的解決方案。我不得不根據用戶界面中的選擇添加'where'子句。 – 2015-07-14 07:00:06

1
results = context.Orders.Where(o => o.OrderDate <= today && today <= o.OrderDate) 

由於您已經在處理訂單,所以選擇不受歡迎。

2

您可以使用& &並將所有條件寫入到相同的where子句中,或者您可以在.Where()。Where()。Where()...等等。

7

如果您在內存中的數據(讀「POCO的集合」)時,您也可以使用PredicateBuilder像這樣堆疊在一起你的表情:

// initial "false" condition just to start "OR" clause with 
var predicate = PredicateBuilder.False<YourDataClass>(); 

if (condition1) 
{ 
    predicate = predicate.Or(d => d.SomeStringProperty == "Tom"); 
} 

if (condition2) 
{ 
    predicate = predicate.Or(d => d.SomeStringProperty == "Alex"); 
} 

if (condition3) 
{ 
    predicate = predicate.And(d => d.SomeIntProperty >= 4); 
} 

return originalCollection.Where<YourDataClass>(predicate.Compile()); 

提到PredicateBuilder的完整源波紋管(但你還可以多帶幾個例子檢查original page):

using System; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Collections.Generic; 

public static class PredicateBuilder 
{ 
    public static Expression<Func<T, bool>> True<T>() { return f => true; } 
    public static Expression<Func<T, bool>> False<T>() { return f => false; } 

    public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>> 
      (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters); 
    } 

    public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>> 
      (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters); 
    } 
} 

注意:我測試過這種方法與Portable Class Library項目和甲肝E可使用.Compile(),使其工作:

凡(謂語.Compile());

+0

有沒有一個原因,這將不適用於實體框架LINQ? – Ciantic 2017-09-11 09:55:30