2012-06-04 16 views
60

tengo una consulta como estaLINQ: añadir condiciones a la cláusula where condicionalmente

(from u in DataContext.Users 
     where u.Division == strUserDiv 
     && u.Age > 18 
     && u.Height > strHeightinFeet 
     select new DTO_UserMaster 
     { 
     Prop1 = u.Name, 
     }).ToList(); 

Quiero añadir las diversas condiciones como la edad, la altura en función de si esas condiciones se proporcionaron al método de ejecución de esta consulta. Todas las condiciones incluirán la división de usuario. Si se proporcionó la edad, quiero agregar eso a la consulta. De manera similar, si se proporcionó altura, también quiero agregar eso.

Si esto se hiciera usando consultas SQL, habría utilizado el generador de cadenas para adjuntarlas a la consulta strSQL principal. Pero aquí en Linq solo puedo pensar en usar una condición IF donde escribiré la misma consulta tres veces, con cada bloque IF teniendo una condición adicional. ¿Hay una mejor manera de hacer esto?

Gracias por su tiempo ..

+0

Hermosa pregunta! con un encabezado bien definido, ¡con una respuesta más hermosa! – Irfan

Respuesta

108

Si usted no llama ToList() y su asignación final para el tipo DTO, puede agregar Where cláusulas sobre la marcha, y construir los resultados al final:

var query = from u in DataContext.Users 
    where u.Division == strUserDiv 
    && u.Age > 18 
    && u.Height > strHeightinFeet 
    select u; 

if (useAge) 
    query = query.Where(u => u.Age > age); 

if (useHeight) 
    query = query.Where(u => u.Height > strHeightinFeet); 

// Build the results at the end 
var results = query.Select(u => new DTO_UserMaster 
    { 
    Prop1 = u.Name, 
    }).ToList(); 

Esto todavía sólo resultará en una llamada única a la base de datos, que será efectivamente tan eficiente como escribir la consulta en una sola pasada.

+0

¿Debo poner todas las condiciones where en la instrucción "var query = .."? – user20358

+1

@ user20358 No, la forma en que está escrita funciona bien. –

+2

Las siguientes condiciones ¿Dónde se agregan como OR o como Y? – Vi100

12

una opción.

bool? age = null 

(from u in DataContext.Users 
      where u.Division == strUserDiv 
      && (age == null || (age != null && u.Age > age.Value)) 
      && u.Height > strHeightinFeet 
      select new DTO_UserMaster 
      { 
      Prop1 = u.Name, 
      }).ToList(); 

o puede cambiar a la sintaxis del método para linq y utilizar si las condiciones para adjuntar expresiones a la cláusula where.

+0

No puedo creer que no haya pensado en esto. – phil

2

Aquí está mi código para hacer algo similar. Este es un método en mi aplicación WCF SOAP Web Service.

public FruitListResponse GetFruits(string color, bool? ripe) 
    { 
     try 
     { 
      FruitContext db = new FruitContext(); 
      var query = db.Fruits.Select(f => f); 
      if (color != null) 
      { 
       query = query.Where(f => f.Color == color); 
      } 
      if (ripe != null) 
      { 
       query = query.Where(f => f.Ripe == ripe); 
      } 
      return new FruitListResponse 
      { 
       Result = query.Select(f => new Fruit { Id = f.FruitId, Name = f.Name }).ToList() 
      }; 
     } 
     catch (Exception e) 
     { 
      return new FruitListResponse { ErrorMessage = e.Message }; 
     } 
    } 

La consulta de base es Select(f => f) que significa básicamente todo, y el Where cláusulas están opcionalmente unido a él. El Select final es opcional. Utilizo para convertir los objetos de las filas de la base de datos en objetos resultantes "Frutas".

+1

nice explanation – xDJR1875

7

Normalmente uso el método de encadenamiento pero tengo el mismo problema. Y aquí está la extensión que uso

public static IQueryable<T> ConditionalWhere<T>(
     this IQueryable<T> source, 
     Func<bool> condition, 
     Expression<Func<T, bool>> predicate) 
    { 
     if (condition()) 
     { 
      return source.Where(predicate); 
     } 

     return source; 
    } 

Ayuda a evitar los cortes de cadena. También son útiles los mismos ConditionalOrderBy y ConditionalOrderByDescending.

+0

Útil, pero podría agregar un ejemplo de cómo se vería en uso. – Suncat2000

+1

Debe ser como: var fruits = aguardar db.Fruits .ConditionalWhere (() => color! = Null, f => f.Color == color) .ConditionalWhere (() => ripe! = Null, f => f.Ripe == maduro) .ToListAsync(); –

+1

¡Funciona muy bien! ¡Gracias! También hice una sobrecarga para * condición * como un valor booleano simple en lugar de una función, para hacerlo más intuitivo cuando un delegado agrega complejidad innecesaria. Uso este método de extensión con bastante frecuencia ahora y aprecio mucho su solución. – Suncat2000

2

Simplemente lo estoy usando en mi cláusula where como

public IList<ent_para> getList(ent_para para){ 
    db.table1.Where(w=>(para.abc!=""?w.para==para.abc:true==true) && (para.xyz!=""?w.xyz==para.xyz:true==true)).ToList(); 
} 
0

Basado en cierta condtion de añadir el estado donde ...

from u in DataContext.Users 
where u.Division == strUserDiv 
&& u.Age != null ? u.Age > 18 : 1== 1 
&& u.Height != null ? u.Height > 18 : 1== 1 
&& u.Height != null ? u.Height > 18 : 1== 1 
select new DTO_UserMaster 
     { 
     Prop1 = u.Name, 
     }).ToList(); 
Cuestiones relacionadas