Dinamico clausola WHERE in LINQ
-
21-08-2019 - |
Domanda
Qual è il modo migliore per assemblare una dinamica clausola WHERE una dichiarazione LINQ?
Ho diverse decine di caselle di controllo su un form e sto passandoli indietro come:. Dictionary
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;
}
Soluzione
(fonte: scottgu.com )
Hai bisogno di qualcosa di simile? Utilizzare il Query dinamica Biblioteca Linq (download include esempi).
Scopri di ScottGu blog per ulteriori esempi.
Altri suggerimenti
È inoltre possibile utilizzare il PredicateBuilder da LinqKit a catena molteplici espressioni lambda typesafe utilizzando Or o E.
Ho scenario simile in cui ho bisogno di aggiungere filtri basati sull'input dell'utente e catena in cui clausola.
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);
Un approccio semplice può essere se le colonne sono di semplice tipo come String
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); });
}
mi si avvicinò con una soluzione che anche io posso capire ... utilizzando il metodo 'Contiene' è possibile concatenare quanti Dov'è che vuoi. Se il WHERE è una stringa vuota, è ignorato (o valutato come un Seleziona tutto). Qui è il mio esempio di unire 2 tavoli in LINQ, applicando multipli in cui le clausole e la compilazione di una classe di modello da restituire alla vista. (Questo è un Seleziona tutto).
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 stessa domanda ( filtro definito utente per LINQ ), e @tvanfosson mi ha parlato di dinamica Linq ( http://code.msdn.microsoft.com/csharpsamples ) .
È possibile utilizzare il metodo di estensione Qualsiasi (). Quanto segue 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 gli oggetti List.
Questo progetto su CodePlex avere quello che vuoi.
System.Linq.Dynamic - http://dynamiclinq.codeplex.com/
Descrizione del progetto
Estende System.Linq.Dynamic per supportare l'esecuzione di espressioni Lambda definiti in una stringa contro Entity Framework o di qualsiasi provider che supporti IQueryable.
Come è un'estensione del codice sorgente si può trovare su Blog di Scott Guthrie vi permetterà di fare cose come questa:
E cose come questa:
Questa è la soluzione mi è venuta se qualcuno è interessato.
https: // kellyschronicles. wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/
Per prima cosa identifichiamo il tipo di elemento singolo abbiamo bisogno di usare (Of Trow Come DataRow) e quindi identificare la “fonte” stiamo usando e legare l'identificatore a quella sorgente ((fonte come TypedTableBase (Of Trow)). Poi abbiamo deve specificare il predicato, o la clausola WHERE che sta per essere passato (predicato come func (di Trow, booleano)), che sia restituita come vera o falsa. Poi ci identifichiamo come vogliamo le informazioni restituite ordinato (OrderByField As String ). la nostra funzione sarà poi restituire un EnumerableRowCollection (Of Trow), la nostra collezione di DataRow che hanno soddisfatto le condizioni del nostro predicato (EnumerableRowCollection (Of Trow)). Questo è un esempio di base. Naturalmente è necessario assicurarsi che il proprio doesn campo ordine 't contengono valori nulli, o hanno gestito quella situazione correttamente e assicurarsi che le nomi delle colonne (se si utilizza un dataSource fortemente tipizzato non importa questo, sarà rinominare le colonne per voi) sono di serie.
Sembra molto più semplice e più semplice da usare l'operatore ternario di decidere in modo dinamico se una condizione è incluso
Lista Lista prodotti = new List ();
productList =
db.ProductDetail.Where(p => p.ProductDetailID > 0 //Example prop
&& (String.IsNullOrEmpty(iproductGroupName) ? (true):(p.iproductGroupName.Equals(iproductGroupName)) ) //use ternary operator to make the condition dynamic
&& (ID == 0 ? (true) : (p.ID == IDParam))
).ToList();