2010-12-08 23 views
12

Busco a utilizar LINQ hacer múltiples donde las condiciones de una colección similares adinámicos LINQ o condiciones

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

a excepción de en lugar de tener múltiples y condiciones (como en este ejemplo), me gustaría tener múltiples condiciones O

EDITAR Lo sentimos, aclarar que no sé cuántas de estas condiciones voy a tener por lo

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

no va a funcionar.

Básicamente, aquí es lo que estoy tratando de hacer:

Respuesta

7

Parece que su lista blanca de nombres solamente se conoce en tiempo de ejecución. Tal vez intente esto:

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

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

Está sido super útil para mí porque yo ya estaba buscando en la biblioteca dinámica LINQ acaba de hacer esto. ¡Gracias! – xleon

13

Uso PredicateBuilder:

Suponga que desea escribir un LINQ a SQL o una consulta de Entity Framework que implementa una búsqueda de estilo de palabras clave. En otras palabras, una consulta que devuelve filas cuya descripción contiene algunos o todos de un conjunto determinado de palabras clave ...

El enfoque ideal es construir dinámicamente un árbol de expresión lambda que lleva a cabo un predicado basado o .

De todas las cosas que lo llevarán a la construcción manual de árboles de expresiones, la necesidad de predicados dinámicos es la más común en una aplicación comercial típica. Afortunadamente, es posible escribir un conjunto de métodos de extensión simples y reutilizables que simplifican radicalmente esta tarea. Este es el papel de nuestra PredicateBuilder clase ...

+0

Buen trabajo, pero no funciona con LINQ to Entities y Entity Framework (6): LINQ to Entities no admite el tipo de nodo de expresión LINQ 'Invoke'. –

10

Puede utilizar .Union() para devolver resultados que satisfacen cualquier condición.

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

Ésta es inferior al utilizar el operador ||. No está claro en su edición por qué eso no funcionaría.

+0

¡Usar la unión es definitivamente un truco inteligente! +1 por eso. – Steven

0

No puede hacer que la cláusula Where sea dinámica, pero puede crear dinámicamente la expresión Lambda que le pase. Cree el Expression correcto, compílelo y pase la expresión lambda resultante como un parámetro a la cláusula Where.

EDIT:

bien, parece como puede omitir la parte donde se tiene que crear manualmente la expresión y puede utilizar PredicateBuilder para ello, como ya se ha contestado por 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; 
    } 

Luego, más tarde:

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 no es admitido por LINQ to Entities :( – yonexbat

+0

@ user288281 si eso es cierto - triste. La manipulación del árbol de expresiones debe ser de nivel .NET Tener instancias LinqToSql o LinqToEntities referenciadas por el árbol no debe influir en su capacidad para crear árboles nuevos desde es más que tener ints o cadenas. –

+0

¿Alguien sabe cómo convertir esta muestra para que funcione con el marco de la entidad. ¿Cómo se puede evitar invocar la expresión? De alguna manera debe ser posible ya que está el http://tomasp.net/blog /linq-expand.aspx framework. – yonexbat

Cuestiones relacionadas