Cláusula WHERE dinámica en LINQ

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

Tengo varias docenas de casillas de verificación en un formulario y las estoy devolviendo como: Diccionario <cadena, Lista > (Diccionario <nombrecampo, Lista >) a mi consulta LINQ.

public IOrderedQueryable GetProductList(string productGroupName, string productTypeName, Dictionary<string,List> 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; } 

texto alternativo http://www.scottgu.com/blogposts/dynquery/step2.png

Necesitas algo como esto? Utilice la Biblioteca de consultas dinámicas de Linq (la descarga incluye ejemplos).

Vea el blog de ScottGu para más ejemplos.

También puede usar PredicateBuilder de LinqKit para encadenar múltiples expresiones lambda de tipo seguro usando O o Y.

http://www.albahari.com/nutshell/predicatebuilder.aspx

Un Enfoque simple puede ser si sus Columnas son de Tipo simple como Cadena

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

Tengo un escenario similar en el que necesito agregar filtros basados ​​en la entrada del usuario y encadenar la cláusula where.

Aquí está el código de ejemplo.

 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); 

Encontré una solución que incluso yo puedo entender … usando el método ‘Contiene’ puedes encadenar tantos DONDE como quieras. 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); } 

Tenía la misma pregunta ( filtro definido por el usuario para linq ), y @tvanfosson me habló de Dynamic Linq ( http://code.msdn.microsoft.com/csharpsamples ).

Puede usar el método de extensión Any (). 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 ambos objetos List.

Este proyecto en CodePlex tiene lo que quieres.

System.Linq.Dynamichttp://dynamiclinq.codeplex.com/

Descripción del Proyecto

Extiende System.Linq.Dynamic para admitir la ejecución de expresiones Lambda definidas en una cadena en Entity Framework o cualquier proveedor que admita IQueryable.

Como es una extensión del código fuente que puedes encontrar en el blog de Scott Guthrie, te permitirá hacer cosas como esta:

enter image description here

Y cosas como esta:

enter image description here

Esta es la solución que surgió si alguien está interesado.

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

Primero identificamos el tipo de elemento único que necesitamos usar (de TRow As DataRow) y luego identificamos la “fuente” que estamos utilizando y vinculamos el identificador a esa fuente ((fuente Como TypedTableBase (Of 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 la información devuelta ordene (OrderByField As String). la función devolverá una EnumerableRowCollection (Of TRow), nuestra colección de datarows que cumplen con las condiciones de nuestro predicado (EnumerableRowCollection (Of TRow)). Este es un ejemplo básico. Por supuesto, debe asegurarse de que su campo de pedido no contenga nulls, 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.