2009-05-11 16 views
46

Jaki jest najlepszy sposób na złożenie dynamicznej klauzuli WHERE do instrukcji LINQ?Dynamiczna klauzula WHERE w LINQ

mam kilkadziesiąt wyboru na formularzu i 'm przechodzącej je z powrotem jako: słownik < ciąg lista < ciąg > > (Słownik < fieldName, Lista < wartości > >) do mojej kwerendy 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; 
} 

Odpowiedz

8

proste podejście może być, jeśli kolumny mają typ prosty jak 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

można użyć Obojętnie() metodę rozszerzenia. Poniższe wydaje się działać dla mnie.

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

Gdzie "fieldsToSearch" i "fieldsToReturn" są obiektami List.

1

Ten projekt na CodePlex ma to, czego potrzebujesz.

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

Opis projektu

Rozszerza System.Linq.Dynamic wspierać wykonanie wyrażeń lambda określonych w ciąg przeciwko Entity Framework lub dowolnego dostawcy, który obsługuje IQueryable.

Jak to jest rozszerzenie kodu źródłowego można znaleźć na Scott Guthrie's Blog pozwoli Ci robić rzeczy tak:

enter image description here

i rzeczy tak:

enter image description here

3

Wymyśliłem rozwiązanie, które nawet ja rozumiem ... za pomocą metody "Zawiera" możesz połączyć w sieć tyle GDZIE, co Ty lubić. Jeśli WHERE jest pustym łańcuchem, zostanie zignorowane (lub ocenione jako zaznaczenie wszystkie). Oto mój przykład dołączenia do 2 tabel w LINQ, stosowania wielu klauzul where i zapełniania klasy modelu, która ma zostać zwrócona do widoku. (to wszystko wybierz).

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

Mam podobny scenariusz, w którym muszę dodać filtry w oparciu o dane wejściowe użytkownika i łańcucha klauzula gdzie.

Oto przykładowy kod.

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

Najlepiej nadaje się do moich potrzeb i jest łatwy w użyciu. Dziękuję Ci. – user6121177

-1

To jest rozwiązanie, które wymyśliłem, jeśli ktoś jest zainteresowany.

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

Najpierw musimy zidentyfikować jeden typ elementu musimy użyć (z Trow Jak DataRow), a następnie określić „źródło” używamy i związać identyfikator do tego źródła ((źródło Jako TypedTableBase (z TRow)) Następnie musimy określić predykat lub klauzulę WHERE, która ma zostać przekazana (predykat As Func (Of TRow, Boolean)), który zostanie zwrócony jako true lub false, a następnie określić, w jaki sposób chcemy zwrócić informacje uporządkowane (OrderByField As String) Nasza funkcja zwróci następnie EnumerableRowCollection (Of TRow), naszą kolekcję datariów, które spełniły warunki naszego predykatu (EnumerableRowCollection (Of TRow)) Jest to podstawowy przykład. upewnij się, że twoje pole zamówienia nie zawiera nu lls, albo poprawnie obsłużyłeś tę sytuację i upewnij się, że twoje nazwy kolumn (jeśli używasz mocno wpisanego źródła danych, nieważne, to zmieni nazwę kolumn dla ciebie) są standardowe.

+0

Link do rozwiązania jest mile widziany, ale upewnij się, że twoja odpowiedź jest przydatna bez niego: [dodaj kontekst wokół linku] (// meta.stackexchange.com/a/8259), aby inni użytkownicy mieli pojęcie, co to jest i dlaczego tam jest, a następnie zacytuj najważniejszą część strony, do której prowadzi link, jeśli strona docelowa jest niedostępna. [Odpowiedzi, które są niewiele więcej niż link, można usunąć.] (// stackoverflow.com/help/deleted-answers) – FelixSFD

+0

Przepraszam. Jestem tu nowy. – KJM

Powiązane problemy