2009-03-10 26 views
64

Estoy trabajando con una consulta LINQ a SQL y me he encontrado con un problema donde tengo 4 campos opcionales para filtrar el resultado de los datos. Por opción, me refiero a que tiene la opción de ingresar un valor o no. En concreto, unos cuadros de texto que podrían tener un valor o que tienen una cadena vacía y unas pocas listas desplegables que podría haber tenido un valor seleccionado o tal vez no ...LINQ to SQL Donde Cláusula Criterio Opcional

Por ejemplo:

using (TagsModelDataContext db = new TagsModelDataContext()) 
    { 
     var query = from tags in db.TagsHeaders 
        where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
        && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE 
        && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE 
        select tags; 
     this.Results = query.ToADOTable(rec => new object[] { query }); 
    } 

Ahora Necesito agregar los siguientes campos/filtros, pero solo si el usuario los proporciona.

  1. Número de producto - Viene de otra tabla que se puede unir a TagsHeaders.
  2. Número de pedido: un campo dentro de la tabla de TagsHeaders.
  3. Número de pedido: similar a PO #, solo una columna diferente.
  4. Estado del producto: si el usuario lo seleccionó de un menú desplegable, debe aplicar aquí el valor seleccionado.

La consulta que ya tengo funciona muy bien, pero para completar la función, necesita poder agregar estos 4 elementos más en la cláusula where, ¡simplemente no sé cómo!

+1

Marque aquí Roscoe, se puede haber sido respondida ya ... [http://stackoverflow.com/questions/11194/conditional-linq-queries](http://stackoverflow.com/questions/11194/conditional-linq-queries) – jlembke

Respuesta

114

puede codificar su búsqueda original:

var query = from tags in db.TagsHeaders 
       where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
       && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE 
       && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE 
       select tags; 

Y a continuación, en base a una condición, añadir adicional donde las restricciones.

if(condition) 
    query = query.Where(i => i.PONumber == "ABC"); 

No estoy seguro de cómo codificar esto con la sintaxis de la consulta, pero la identificación funciona con una lambda. También funciona con sintaxis de consulta para la consulta inicial y una lambda para el filtro secundario.

También puede incluir un método de extensión (a continuación) que codifiqué hace un tiempo para incluir sentencias condicionales. (No funciona bien con la sintaxis de consulta):

 var query = db.TagsHeaders 
      .Where(tags => tags.CST.Equals(this.SelectedCust.CustCode.ToUpper())) 
      .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE) 
      .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE) 
      .WhereIf(condition1, tags => tags.PONumber == "ABC") 
      .WhereIf(condition2, tags => tags.XYZ > 123); 

El método de extensión:

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

aquí es el mismo método de extensión para IEnumerables:

public static IEnumerable<TSource> WhereIf<TSource>(
    this IEnumerable<TSource> source, bool condition, 
    Func<TSource, bool> predicate) 
{ 
    if (condition) 
     return source.Where(predicate); 
    else 
     return source; 
} 
+1

+1 Eso realmente limpia el código y se comunica mucho mejor – jlembke

+3

+10 Muchas gracias por la respuesta. Justo lo que estaba buscando. Realmente aprecio que te tomes el tiempo para hacer esto. – RSolberg

+0

Sin problema Amo cosas como esta. – andleer

26

Solo necesita usar una comprobación condicional para la existencia del parámetro. Por ejemplo:

where (string.IsNullOrEmpty(ProductNumber) || ProductNumber == tags.productNumber) 

De esta forma si el número de productos que no se introduce la expresión devolverá cierto en todos los casos, pero si se introduce sólo devolverá cierto cuando juego.

+0

+1 Eso es bonito.Estaba tratando de pensar en algo similar anteriormente – jlembke

+0

+1 Estaba tratando de encontrar una solución elegante para 'condicional donde' en mi caso tuve múltiples uniones y resultados devolviendo registros de una tabla unida. ¡Trabajado como un encanto! – AidaM