Dynamiczna klauzula WHERE w LINQ

Jaki jest najlepszy sposób na złożenie klauzuli dynamic WHERE do instrukcji LINQ?

Mam kilkadziesiąt checkboxów w formularzu i przekazuję je z powrotem jako: Dictionary >(Dictionary>) do mojego zapytania 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;
}
Author: abatishchev, 2009-05-11

9 answers

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

Potrzebujesz czegoś takiego? Użyj dynamicznej Biblioteki zapytań Linq (Pobieranie zawiera przykłady).

Więcej przykładów znajdziesz na blogu ScottGu.
 50
Author: Thomas Stock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-11 14:39:31

Można również użyć PredicateBuilder z LinqKit do łączenia wielu typów wyrażeń lambda za pomocą Or Lub And.

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

 11
Author: Linus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-13 01:08:24

Proste podejście może być, jeśli Twoje kolumny są prostego typu 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); });
}
 8
Author: Nitin Bourai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-19 13:17:19

Mam podobny scenariusz, w którym muszę dodać filtry na podstawie danych wejściowych użytkownika i łańcuchem klauzuli where.

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);
 7
Author: Xavier John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-30 00:28:33

Wymyśliłem rozwiązanie, które nawet ja mogę zrozumieć... korzystając z metody "Contains", możesz łańcuchować tyle, ile chcesz. Jeśli WHERE jest pustym łańcuchem znaków, jest on ignorowany (lub oceniany jako select all). Oto mój przykład łączenia 2 tabel w LINQ, stosowania wielu klauzul where I wypełniania klasy modelu, która ma zostać zwrócona do widoku. (to jest Zaznacz wszystko).

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
Author: mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-28 23:26:41

Miałem to samo pytanie (User defined filter for linq), a @tvanfosson powiedział mi o dynamicznym Linq ( http://code.msdn.microsoft.com/csharpsamples ).

 2
Author: TcKs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:42

Możesz użyć metody rozszerzenia Any (). Wygląda na to, że dla mnie to działa.

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
Author: Todd DeLand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-27 17:52:44

Ten projekt na CodePlex ma to, czego chcesz.

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

Opis Projektu

Rozszerza System.Linq.Dynamic do obsługi wykonywania wyrażeń Lambda zdefiniowanych w łańcuchu znaków w stosunku do encji Framework lub dowolnego dostawcy obsługującego IQueryable.

Ponieważ jest to rozszerzenie kodu źródłowego, które można znaleźć na blogu Scotta Guthrie pozwoli Ci to robić rzeczy tak:

Tutaj wpisz opis obrazka

I takie rzeczy:

Tutaj wpisz opis obrazka

 1
Author: Zignd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-21 20:09:52

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 identyfikujemy Typ pojedynczego elementu, którego musimy użyć (of TRow As DataRow), a następnie identyfikujemy "źródło", którego używamy i przywiązujemy identyfikator do tego źródła ((source As TypedTableBase (of TRow)). Następnie musimy określić predykat lub klauzulę WHERE, która ma zostać przekazana (predykat jako Func (of TRow, Boolean)), które zostaną zwrócone jako true lub false. Następnie określamy, w jaki sposób chcemy uporządkować zwracane informacje (OrderByField jako String). Nasza funkcja zwróci następnie EnumerableRowCollection( of TRow), nasz zbiór danych, które spełniły warunki naszego predykatu(EnumerableRowCollection(of TRow)). Jest to podstawowy przykład. Oczywiście musisz upewnić się, że Twoje pole zamówienia nie zawiera null, lub poprawnie obsłużyłeś tę sytuację i upewnij się, że Twoje nazwy kolumn (jeśli jesteś korzystanie z silnie wpisanego źródła danych nieważne to, zmieni nazwę kolumn dla ciebie) są standardowe.

 1
Author: KJM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-17 18:59:05