Warunkowe Zapytania Linq

Pracujemy nad przeglądarką dziennika. Użycie będzie miało opcję filtrowania według użytkownika, ważności itp. W dniach Sql dodałbym do ciągu zapytania, ale chcę to zrobić z Linq. Jak warunkowo dodać klauzule where?

Author: Keith, 2008-08-14

12 answers

Jeśli chcesz filtrować tylko wtedy, gdy spełnione są określone kryteria, zrób coś takiego

var logs = from log in context.Logs
           select log;

if (filterBySeverity)
    logs = logs.Where(p => p.Severity == severity);

if (filterByUser)
    logs = logs.Where(p => p.User == user);

W ten sposób twoje drzewo wyrazów będzie dokładnie tym, czego chcesz. W ten sposób stworzony SQL będzie dokładnie tym, czego potrzebujesz i nie mniej.

 144
Author: Darren Kopp,
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
2010-07-16 18:00:35

Jeśli chcesz filtrować bazę na liście / tablicy użyj następującego:

    public List<Data> GetData(List<string> Numbers, List<string> Letters)
    {
        if (Numbers == null)
            Numbers = new List<string>();

        if (Letters == null)
            Letters = new List<string>();

        var q = from d in database.table
                where (Numbers.Count == 0 || Numbers.Contains(d.Number))
                where (Letters.Count == 0 || Letters.Contains(d.Letter))
                select new Data
                {
                    Number = d.Number,
                    Letter = d.Letter,
                };
        return q.ToList();

    }
 21
Author: Carlos,
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
2011-05-09 19:36:13

Skończyłem używając odpowiedzi podobnej do Darena, ale z interfejsem IQueryable:

IQueryable<Log> matches = m_Locator.Logs;

// Users filter
if (usersFilter)
    matches = matches.Where(l => l.UserName == comboBoxUsers.Text);

 // Severity filter
 if (severityFilter)
     matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);

 Logs = (from log in matches
         orderby log.EventTime descending
         select log).ToList();

, który tworzy zapytanie przed uderzeniem w bazę danych. Dowództwo nie uruchomi się do czasu .ToList () na końcu.

 19
Author: sgwill,
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
2008-08-21 13:50:32

Jeśli chodzi o LINQ warunkowe, bardzo lubię filtry i rury wzór.
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/

Zasadniczo tworzysz metodę rozszerzenia dla każdego przypadku filtra, który bierze w IQueryable i parametr.

public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
    return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}
 13
Author: Lars Mæhlum,
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
2008-08-14 22:03:19

Inną opcją byłoby użycie czegoś takiego jak PredicateBuilder omawiany tutaj . Pozwala na pisanie kodu w następujący sposób:

var newKids  = Product.ContainsInDescription ("BlackBerry", "iPhone");

var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
                  .And (Product.IsSelling());

var query = from p in Data.Products.Where (newKids.Or (classics))
            select p;

Zauważ, że mam to tylko do pracy z Linq 2 SQL. EntityFramework nie implementuje wyrażenia.Invoke, co jest wymagane do działania tej metody. Mam pytanie odnośnie tej kwestii Tutaj .

 3
Author: Brad Leach,
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 12:16:56

Robi to:

bool lastNameSearch = true/false; // depending if they want to search by last name,

Mając to w where stwierdzeniu:

where (lastNameSearch && name.LastNameSearch == "smith")

Oznacza, że gdy zostanie utworzone ostateczne zapytanie, jeśli lastNameSearch jest false, zapytanie całkowicie pominie dowolny SQL dla wyszukiwania nazwiska.

 3
Author: Craig Livingston,
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
2011-12-26 19:42:57

Nie jest to najładniejsza rzecz, ale możesz użyć wyrażenia lambda i opcjonalnie spełnić swoje warunki. W TSQL robię wiele z następujących rzeczy, aby parametry były opcjonalne:

Gdzie pole = @FieldVar lub @FieldVar jest NULL

Możesz zduplikować ten sam styl za pomocą następującego lambda (przykład sprawdzania uwierzytelniania):

MyDataContext db = new MyDataContext ();

Void RunQuery (string param1, string param2, int? param3) {

Func checkUser = user = >

((param1.Długość > 0)? użytkownik.Param1 = = param1 : 1 == 1) &&

((param2.Długość > 0)? użytkownik.Param2 = = param2 : 1 == 1) &&

((param3 != null)? użytkownik.Param3 = = param3 : 1 == 1);

User foundUser = db.Użytkowników.SingleOrDefault (checkUser);

}

 1
Author: t3rse,
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
2008-08-14 15:53:50

Miałem podobny wymóg Ostatnio i w końcu znalazłem to w he MSDN. Csharp sample dla Visual Studio 2008

Klasy zawarte w próbce DynamicQuery do pobrania pozwalają na tworzenie dynamicznych zapytań w czasie wykonywania w następującym formacie:

var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");

Za pomocą tego można zbudować łańcuch zapytania dynamicznie w czasie wykonywania i przekazać go do metody Where ():

string dynamicQueryString = "City = \"London\" and Order.Count >= 10"; 
var q = from c in db.Customers.Where(queryString, null)
        orderby c.CompanyName
        select c;
 1
Author: Andy Rose,
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
2008-08-18 13:12:06

Rozwiązałem to za pomocą metody rozszerzenia, aby umożliwić warunkowe włączenie LINQ w środku płynnego wyrażenia. Eliminuje to konieczność rozdzielania wyrażenia wyrażeniami if.

.If() metoda rozszerzenia:

public static IQueryable<TSource> If<TSource>(
        this IQueryable<TSource> source,
        bool condition,
        Func<IQueryable<TSource>, IQueryable<TSource>> branch)
    {
        return condition ? source : branch(source);
    }

To pozwala ci to zrobić:

return context.Logs
     .If(filterBySeverity, q => q.Where(p => p.Severity == severity))
     .If(filterByUser, q => q.Where(p => p.User == user))
     .ToList();
 1
Author: Ryan,
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
2018-07-11 06:50:53

Po prostu użyj operatora C#'S&&:

var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical")

Edit: ach, trzeba czytać uważniej. Chcesz wiedzieć jak warunkowo dodać dodatkowe klauzule. W takim razie nie mam pojęcia. :) Prawdopodobnie zrobiłbym tylko przygotowanie kilku zapytań i wykonanie właściwego, w zależności od tego, czego potrzebowałem.

 0
Author: TheSmurf,
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
2008-08-14 15:26:12

Możesz użyć zewnętrznej metody:

var results =
    from rec in GetSomeRecs()
    where ConditionalCheck(rec)
    select rec;

...

bool ConditionalCheck( typeofRec input ) {
    ...
}

To by zadziałało, ale nie da się podzielić na drzewa wyrażeń, co oznacza, że Linq do SQL uruchomi kod sprawdzający z każdym rekordem.

Alternatywnie:

var results =
    from rec in GetSomeRecs()
    where 
        (!filterBySeverity || rec.Severity == severity) &&
        (!filterByUser|| rec.User == user)
    select rec;

To może działać w drzewach wyrażeń, co oznacza, że LINQ do SQL będzie zoptymalizowany.

 0
Author: Keith,
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
2008-08-14 15:34:29

Cóż, myślałem, że możesz umieścić warunki filtra w ogólnej liście predykatów:

    var list = new List<string> { "me", "you", "meyou", "mow" };

    var predicates = new List<Predicate<string>>();

    predicates.Add(i => i.Contains("me"));
    predicates.Add(i => i.EndsWith("w"));

    var results = new List<string>();

    foreach (var p in predicates)
        results.AddRange(from i in list where p.Invoke(i) select i);               

Daje to listę zawierającą "ja", "meyou" i "mow".

Możesz to zoptymalizować, wykonując foreach z predykatami w zupełnie innej funkcji, która ORs wszystkie predykaty.

 0
Author: Jon Limjap,
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
2008-08-14 15:39:33