2009-05-11 21 views
46

Was ist der beste Weg, eine dynamische WHERE-Klausel zu einer LINQ-Anweisung zusammenzustellen?Dynamische WHERE-Klausel in LINQ

Ich habe mehrere Dutzend Kontrollkästchen in einem Formular und sie am Übergang zurück: Wörterbuch < String, List <String> > (Dictionary < Feldname, List <Werte> >) auf meine LINQ-Abfrage.

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

Antwort

8

Ein einfacher Ansatz kann sein, wenn Ihre Spalten der einfachen Art sind wie 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); }); 
} 
1

Sie könnten die Any() Erweiterungsmethode verwenden. Das folgende scheint für mich zu funktionieren.

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

Wobei 'fieldsToSearch' und 'fieldsToReturn' beide Listenobjekte sind.

1

Dieses Projekt auf CodePlex haben, was Sie wollen.

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

Projektbeschreibung

System.Linq.Dynamic Verlängert Ausführung von Lambda-Ausdrücke in einer Kette gegen Entity Framework oder jeden Provider definiert zu unterstützen, unterstützt IQueryable.

Da es sich um eine Erweiterung des Quellcodes ist, dass Sie auf Scott Guthrie's Blog finden kann es Ihnen solche Dinge tun können:

enter image description here

Und Dinge wie diese:

enter image description here

3

Ich kam mit einer Lösung, die sogar ich verstehen kann ... mit der 'Contains' Methode können Sie so viele wie Sie ketten mögen. Wenn das WHERE eine leere Zeichenfolge ist, wird es ignoriert (oder als alle ausgewählt). Hier ist mein Beispiel für das Verknüpfen von 2 Tabellen in LINQ, das Anwenden mehrerer where-Klauseln und das Füllen einer Modellklasse, die an die Ansicht zurückgegeben werden soll. (Dies ist ein Alles auswählen).

4

Ich habe ähnliches Szenario, wo ich Filter basierend auf der Benutzereingabe hinzufügen muss und ich die Where-Klausel Kette.

Hier ist der Beispielcode.

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

Am besten für meine Bedürfnisse geeignet und einfach zu bedienen. Vielen Dank. – user6121177

-1

Dies ist die Lösung, die ich gefunden habe, wenn jemand interessiert ist.

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

Zuerst identifizieren wir die einzelnen Elementtyp wir (Of TRow Wie DataRow) und dann identifizieren die „Quelle“ wir verwenden und binden die Kennung zu dieser Quelle ((Quelle Als TypedTableBase verwenden müssen (Of Dann müssen wir das Prädikat angeben, oder die WHERE-Klausel, die übergeben wird (Prädikat As Func (Of TRow, Boolean)), die entweder als wahr oder falsch zurückgegeben wird. Dann identifizieren wir, wie wir das zurückgeben wollen Informationen geordnet (OrderByField As String). Unsere Funktion wird dann eine EnumerableRowCollection (Of TRow), unsere Sammlung von Datenzeilen, die die Bedingungen unseres Prädikats (EnumerableRowCollection (Of TRow)) erfüllt haben. Dies ist ein grundlegendes Beispiel. Natürlich müssen Sie vergewissere dich, dass dein Bestellfeld kein nu enthält lls, oder habe diese Situation richtig gehandhabt und stelle sicher, dass deine Spaltennamen (wenn du eine stark typisierte Datenquelle verwendest, egal, dies wird die Spalten für dich umbenennen) Standard sind.

+0

Ein Link zu einer Lösung ist willkommen, aber stellen Sie bitte sicher, dass Ihre Antwort ohne sie nützlich ist: [Fügen Sie einen Kontext um den Link hinzu] (// meta.stackexchange.com/a/8259), damit Ihre Mitbenutzer eine Idee haben, was es ist und warum es dort ist, zitieren Sie dann den relevantesten Teil der Seite, auf den Sie verlinken, falls die Zielseite nicht verfügbar ist. [Antworten, die etwas mehr als ein Link sind, können gelöscht werden.] (// stackoverflow.com/help/deleted-answers) – FelixSFD

+0

Ich entschuldige mich. Ich bin neu hier. – KJM