2009-05-11 38 views
46

¿Cuál es la mejor manera de ensamblar una cláusula WHERE dinámica a una instrucción LINQ?Cláusula WHERE dinámica en LINQ

que tienen varias docenas de casillas de verificación en un formulario y los estoy pasando atrás como: Diccionario < cadena, cadena Lista < > > (Diccionario < fieldName, Lista <valores> >) a mi consulta LINQ.

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary) 
{ 
    var q = from c in db.ProductDetail 
      where c.ProductGroupName == productGroupName && c.ProductTypeName == productTypeName 
      // insert dynamic filter here 
      orderby c.ProductTypeName 
      select c; 
    return q; 
} 

Respuesta

8

Un enfoque simple puede ser si sus columnas son de tipo simple como cuerdas

public static IEnumerable<MyObject> WhereQuery(IEnumerable<MyObject> source, string columnName, string propertyValue) 
{ 
    return source.Where(m => { return m.GetType().GetProperty(columnName).GetValue(m, null).ToString().StartsWith(propertyValue); }); 
} 
1

Se puede usar el método de extensión Cualquier(). Lo siguiente parece funcionar para mí.

XStreamingElement root = new XStreamingElement("Results", 
       from el in StreamProductItem(file) 
       where fieldsToSearch.Any(s => el.Element(s) != null && el.Element(s).Value.Contains(searchTerm)) 
       select fieldsToReturn.Select(r => (r == "product") ? el : el.Element(r)) 
      ); 
      Console.WriteLine(root.ToString()); 

Donde 'fieldsToSearch' y 'fieldsToReturn' son los dos objetos List.

1

Este proyecto en CodePlex tiene lo que desea.

System.Linq.Dynamic - http://dynamiclinq.codeplex.com/

Descripción del Proyecto

Extiende System.Linq.Dynamic para apoyar la ejecución de las expresiones lambda definidos en una cadena contra el marco de la entidad o de cualquier proveedor que admite IQueryable.

Como se trata de una extensión del código fuente se puede encontrar en Scott Guthrie's Blog que le permitirá hacer cosas como esta:

enter image description here

Y cosas como esta:

enter image description here

3

Encontré una solución que incluso yo puedo entender ... usando el método 'Contiene' puedes encadenar tantos DONDE como tú me gusta. Si WHERE es una cadena vacía, se ignora (o se evalúa como una selección de todo). Aquí está mi ejemplo de unir 2 tablas en LINQ, aplicar múltiples cláusulas where y rellenar una clase de modelo para devolverla a la vista. (esto es un seleccionar todo).

public ActionResult Index() 
    { 
     string AssetGroupCode = ""; 
     string StatusCode = ""; 
     string SearchString = ""; 

     var mdl = from a in _db.Assets 
        join t in _db.Tags on a.ASSETID equals t.ASSETID 
        where a.ASSETGROUPCODE.Contains(AssetGroupCode) 
        && a.STATUSCODE.Contains(StatusCode) 
        && (
        a.PO.Contains(SearchString) 
        || a.MODEL.Contains(SearchString) 
        || a.USERNAME.Contains(SearchString) 
        || a.LOCATION.Contains(SearchString) 
        || t.TAGNUMBER.Contains(SearchString) 
        || t.SERIALNUMBER.Contains(SearchString) 
       ) 
        select new AssetListView 
        { 
         AssetId = a.ASSETID, 
         TagId = t.TAGID, 
         PO = a.PO, 
         Model = a.MODEL, 
         UserName = a.USERNAME, 
         Location = a.LOCATION, 
         Tag = t.TAGNUMBER, 
         SerialNum = t.SERIALNUMBER 
        }; 


     return View(mdl); 
    } 
4

I tienen escenario similar donde necesito añadir filtros basados ​​en la entrada del usuario y I de cadena El cláusula where.

Aquí está el código de muestra.

var votes = db.Votes.Where(r => r.SurveyID == surveyId); 
if (fromDate != null) 
{ 
    votes = votes.Where(r => r.VoteDate.Value >= fromDate); 
} 
if (toDate != null) 
{ 
    votes = votes.Where(r => r.VoteDate.Value <= toDate); 
} 
votes = votes.Take(LimitRows).OrderByDescending(r => r.VoteDate); 
+0

Ideal para mi necesidad y fácil de usar. Gracias. – user6121177

-1

Esta es la solución que se me ocurrió si a alguien le interesa.

https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/

Primero identificar el tipo de elemento único que tenemos que utilizar (De TROW Como DataRow) y luego identificar la “fuente” estamos utilizando y atar el identificador a esa fuente ((fuente Como TypedTableBase (De TRow)). Luego, debemos especificar el predicado, o la cláusula WHERE que se va a pasar (predicado como Func (Of TRow, Boolean)) que se devolverá como verdadero o falso. A continuación, identificaremos cómo queremos que se devuelva información ordenada (OrderByField As String). Nuestra función devolverá una EnumerableRowCollection (Of TRow), nuestra colección de datarows que han cumplido las condiciones de nuestro predicado (EnumerableRowCollection (Of TRow)). Este es un ejemplo básico. Por supuesto, debe asegúrese de que su campo de pedido no contenga nu lls, o han manejado esa situación correctamente y se aseguran de que los nombres de sus columnas (si está utilizando un origen de datos fuertemente tipado no importen, cambiarán el nombre de las columnas) son estándar.

+0

Un enlace a una solución es bienvenido, pero asegúrese de que su respuesta sea útil sin él: [agregue contexto alrededor del enlace] (// meta.stackexchange.com/a/8259) para que los demás usuarios tengan una idea de lo que es y por qué está allí, luego cita la parte más relevante de la página a la que estás enlazando en caso de que la página objetivo no esté disponible. [Las respuestas que son poco más que un enlace se pueden eliminar.] (// stackoverflow.com/help/deleted-answers) – FelixSFD

+0

Me disculpo. Soy nuevo aquí. – KJM

Cuestiones relacionadas