Clausola WHERE dynamic in LINQ

Qual è il modo migliore per assemblare una clausola WHERE dynamic su una istruzione LINQ?

Ho diverse dozzine di checkbox su un modulo e le sto restituendo come: Dictionary <string, List > (Dictionary <fieldName, List >) alla mia query 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; } 

alt text http://www.scottgu.com/blogposts/dynquery/step2.png

Hai bisogno di qualcosa del genere? Utilizzare la libreria di query dynamic Linq (il download include esempi).

Controlla il blog di ScottGu per altri esempi.

È inoltre ansible utilizzare PredicateBuilder di LinqKit per concatenare più espressioni lambda typesafe utilizzando Or o And.

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

Un semplice approccio può essere se le tue colonne sono di tipo semplice come stringa

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

Ho uno scenario simile in cui ho bisogno di aggiungere filtri basati sull’input dell’utente e concatenare la clausola where.

Ecco il codice di esempio.

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

Ho trovato una soluzione che anche io riesco a capire … usando il metodo ‘Contains’ puoi concatenare tutti i WHERE che vuoi. Se WHERE è una stringa vuota, viene ignorata (o valutata come seleziona tutto). Ecco il mio esempio di unione di 2 tabelle in LINQ, applicazione di più clausole where e compilazione di una class del modello da restituire alla vista. (questo è un select all).

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

Ho avuto la stessa domanda ( filtro definito dall’utente per linq ) e @tvanfosson mi ha parlato di Dynamic Linq ( http://code.msdn.microsoft.com/csharpsamples ).

È ansible utilizzare il metodo di estensione Any (). Il seguente sembra funzionare per me.

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

Dove “fieldsToSearch” e “fieldsToReturn” sono entrambi oggetti List.

Questo progetto su CodePlex ha quello che vuoi.

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

descrizione del progetto

Estende System.Linq.Dynamic per supportare l’esecuzione di espressioni Lambda definite in una stringa contro Entity Framework o qualsiasi provider che supporta IQueryable.

Dato che è un’estensione del codice sorgente che puoi trovare su Scott Guthrie’s Blog ti permetterà di fare cose come questa:

inserisci la descrizione dell'immagine qui

E cose del genere:

inserisci la descrizione dell'immagine qui

Questa è la soluzione che ho trovato se qualcuno fosse interessato.

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

Per prima cosa identifichiamo il singolo tipo di elemento che dobbiamo usare (Of TRow As DataRow) e quindi identifichiamo la “fonte” che stiamo usando e leghiamo l’identificatore a quella fonte ((source As TypedTableBase (Of TRow)). Quindi dobbiamo specificare predicato, o la clausola WHERE che deve essere passata (predicato As Func (Of TRow, Boolean)) che verrà restituito come vero o falso, quindi identifichiamo come vogliamo ordinare le informazioni restituite (OrderByField As String). la funzione restituirà quindi una EnumerableRowCollection (Of TRow), la nostra raccolta di datarows che ha soddisfatto le condizioni del nostro predicato (EnumerableRowCollection (Of TRow)) .Questo è un esempio di base. Ovviamente è necessario assicurarsi che il campo dell’ordine non contenga null, o hanno gestito correttamente questa situazione e assicurati che i nomi delle tue colonne (se stai usando un’origine dati fortemente tipizzata non importa, questo rinominerà le colonne per te) sono standard.