2010-12-08 45 views
12

我期待使用LINQ做多,其中在收集類似動態LINQ和條件

IEnumerable<Object> items; 
items.Where(p => p.FirstName = "John"); 
items.Where(p => p.LastName = "Smith"); 

除了而非使用多個AND條件(如本例中)的條件下,我想有多個OR條件。

編輯 對不起,澄清我不知道我將有多少這些條件使

items.Where(p => p.FirstName = "John" || p => p.LastName = "Smith") 

將無法​​正常工作。

基本上,這裏是我想要做什麼:

回答

7

這聽起來像你的名字的白名單僅在運行時知道。也許試試這個:

string[] names = new string[] {"John", "foo", "bar"}; 

var matching = items.Where(x => names.Contains(x.Name)); 
+0

It's一直是我的超級有用的,因爲我已經在看LINQ的動態庫只是爲了做到這一點。謝謝! – xleon 2015-06-24 01:16:12

13

使用PredicateBuilder

假設你想要寫一個LINQ to SQL的或實現一個關鍵詞的搜索式的實體框架查詢。換句話說,查詢返回行其描述包含部分或全部給定一組關鍵詞的...

理想的方法是動態地構建執行基於謂詞lambda表達式樹。

在推動您手動構建表達式樹的所有事情中,動態謂詞的需求是典型業務應用程序中最常見的。幸運的是,可以編寫一套簡單且可重用的擴展方法,從根本上簡化了這一任務。這是我們PredicateBuilder類的角色......

+0

幹得好,但不適用於LINQ to Entities和實體框架(6):LINQ to Entities不支持LINQ表達式節點類型「Invoke」。 – 2016-12-13 10:51:20

10

您可以使用.Union()返回滿足任何條件的結果。

var results = items.Where(p => p.FirstName == "John") 
    .Union(items.Where(p => p.LastName == "Smith")); 

這比使用||算子差。從你的編輯中不清楚爲什麼這不起作用。

+0

使用工會絕對是一個聰明的把戲! +1。 – Steven 2010-12-08 19:05:09

0

您不能使Where子句變爲動態,但可以動態創建傳遞給它的Lambda表達式。創建正確的Expression,編譯它並將生成的lambda表達式作爲參數傳遞給Where子句。

編輯:

好了,好像你可以跳過,你必須手動創建的表達可以用PredicateBuilder它的一部分,已經被AS-CII回答。

2
public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
     this IEnumerable<Expression<Func<T, bool>>> filters) 
    { 
     Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault(); 
     if (firstFilter == null) 
     { 
      Expression<Func<T, bool>> alwaysTrue = x => true; 
      return alwaysTrue; 
     } 

     var body = firstFilter.Body; 
     var param = firstFilter.Parameters.ToArray(); 
     foreach (var nextFilter in filters.Skip(1)) 
     { 
      var nextBody = Expression.Invoke(nextFilter, param); 
      body = Expression.OrElse(body, nextBody); 
     } 
     Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param); 
     return result; 
    } 

然後,後來:

List<Expression<Func<Person, bool>>> filters = names 
    .Select<string, Expression<Func<Person, bool>>>(name => 
    p => p.Name == name 
).ToList(); 

Expression<Func<Person, bool>> filterOfOrs = filters.OrTheseFiltersTogether(); 

query = query.Where<Person>(filterOfOrs); 
+0

調用不支持LINQ到實體:( – yonexbat 2011-08-28 18:57:32