2010-12-08 20 views
12

Je cherche à utiliser LINQ pour faire plusieurs où les conditions sur une collection similaire àdynamique LINQ OU Conditions

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

sauf pour plutôt que d'avoir des conditions multiples et (comme cet exemple), je voudrais avoir plusieurs conditions OR.

EDIT Désolé, pour préciser que je ne sais pas combien de ces conditions, j'aurai donc

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

ne fonctionnera pas.

En gros, voici ce que je suis en train de faire:

Répondre

7

Il ressemble à votre liste blanche des noms est connu que lors de l'exécution. Peut-être essayer ceci:

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

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

été super utile d'une manière pour moi parce que je cherchais déjà à la bibliothèque dynamique LINQ juste pour le faire. Merci! – xleon

13

Utilisation PredicateBuilder:

Supposons que vous voulez écrire un LINQ to SQL ou une requête Entity Framework qui implémente une recherche de style mot-clé. En d'autres termes, une requête qui renvoie des lignes dont la description contient partie ou la totalité d'un ensemble de mots-clés ...

L'idéal est de construire dynamiquement un arbre d'expression lambda qui effectue une ou prédicat à base . De toutes les choses qui vous permettront de construire manuellement des arbres d'expression, le besoin de prédicats dynamiques est le plus courant dans une application métier typique. Heureusement, il est possible d'écrire un ensemble de méthodes d'extension simples et réutilisables qui simplifient radicalement cette tâche. Tel est le rôle de notre PredicateBuilder classe ...

+0

Beau travail, mais ne fonctionne pas avec LINQ to Entities et Entity Framework (6): Le type de noeud d'expression LINQ 'Invoke' n'est pas supporté dans LINQ to Entities. –

10

Vous pouvez utiliser .Union() pour retourner des résultats qui répondent à toutes les conditions.

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

Ceci est inférieur à l'aide de l'opérateur ||. Il n'est pas clair à partir de votre édition pourquoi cela ne fonctionnerait pas.

+0

L'utilisation de l'union est certainement une astuce intelligente! +1 pour ça. – Steven

0

Vous ne pouvez pas rendre la clause Where dynamique, mais vous pouvez créer dynamiquement l'expression Lambda que vous lui transmettez. Créez le droit Expression, compilez-le et passez l'expression lambda résultante en tant que paramètre à la clause Where.

EDIT:

Ok, semble que vous pouvez sauter la partie où vous devez créer manuellement l'expression et peut utiliser PredicateBuilder pour elle, comme cela a déjà répondu par 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; 
    } 

Puis, plus tard:

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

Invoke n'est pas pris en charge par LINQ to Entities :( – yonexbat

+0

@ user288281 si cela est vrai - triste La manipulation de l'arbre d'expression doit être de niveau .net Les instances LinqToSql ou LinqToEntities référencées par l'arbre ne doivent pas influencer votre capacité à créer de nouveaux arbres. –

+0

Est-ce que quelqu'un sait comment convertir cet exemple pour qu'il fonctionne avec le framework d'entité Comment peut-on éviter d'invoquer l'expression? Il doit en quelque sorte être possible car http://tomasp.net/blog /linq-expand.aspx framework. – yonexbat