Сведения о вопросе

Ayrat

02:35, 13th August, 2020

Теги

c#   linq   linq-to-sql   .net-3.5    

Условные Запросы Linq

Просмотров: 482   Ответов: 13

Мы работаем над средством просмотра журналов. Использование будет иметь возможность фильтровать по пользователю, серьезности и т.д. В Sql дней я бы добавил к строке запроса, но я хочу сделать это с Linq. Как я могу условно добавить, где предложения?



  Сведения об ответе

PROGA

04:21, 15th August, 2020

если вы хотите отфильтровать только определенные критерии, выполните что-то вроде этого

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

Это позволит вашему дереву выражений быть именно тем, что вы хотите. Таким образом, созданный SQL будет именно тем, что вам нужно, и не меньше.


  Сведения об ответе

#hash

03:40, 17th August, 2020

Если вам нужно отфильтровать базу по списку / массиву, используйте следующее:

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

    }


  Сведения об ответе

DINO

09:46, 1st August, 2020

Я закончил использовать ответ, похожий на ответ Дарена, но с интерфейсом 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();

Это создает запрос перед попаданием в базу данных. Команда не будет выполняться до тех пор, пока .ToList() в самом конце.


  Сведения об ответе

prince

15:44, 24th August, 2020

Когда дело доходит до условного linq, я очень люблю паттерн фильтров и труб.
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/

В основном вы создаете метод расширения для каждого случая фильтра, который принимает IQueryable и параметр.

public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
    return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}


  Сведения об ответе

DAAA

12:12, 28th August, 2020

Другой вариант - использовать что-то вроде PredicateBuilder, обсуждаемого здесь . Он позволяет вам писать код следующим образом:

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;

Обратите внимание, что я получил это только для работы с Linq 2 SQL. EntityFramework не реализует Expression.Invoke, что необходимо для работы этого метода. У меня есть вопрос по этому вопросу здесь .


  Сведения об ответе

screen

21:48, 21st August, 2020

Делающий это:

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

имея это в заявлении where :

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

это означает, что при создании окончательного запроса, если lastNameSearch -это false , запрос полностью опустит любой SQL для поиска по фамилии.


  Сведения об ответе

SKY

00:59, 1st August, 2020

Я решил это с помощью метода расширения, чтобы позволить LINQ быть условно включенным в середине свободного выражения. Это устраняет необходимость разбивать выражение На операторы if .

.If() метод расширения:

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

Это позволяет вам сделать следующее:

return context.Logs
     .If(filterBySeverity, q => q.Where(p => p.Severity == severity))
     .If(filterByUser, q => q.Where(p => p.User == user))
     .ToList();

Вот также версия IEnumerable<T> , которая будет обрабатывать большинство других выражений LINQ:

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


  Сведения об ответе

ЯЯ__4

06:06, 10th August, 2020

Недавно у меня было аналогичное требование, и в конце концов я нашел его в he MSDN. CSharp примеры для Visual Studio 2008

Классы, включенные в образец загрузки DynamicQuery, позволяют создавать динамические запросы во время выполнения в следующем формате:

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

С его помощью можно динамически построить строку запроса во время выполнения и передать ее в метод Where():

string dynamicQueryString = "City = \"London\" and Order.Count >= 10"; 
var q = from c in db.Customers.Where(queryString, null)
        orderby c.CompanyName
        select c;


  Сведения об ответе

9090

05:36, 17th August, 2020

Это не самая красивая вещь, но вы можете использовать выражение lambda и передавать свои условия по желанию. В TSQL я делаю много следующего, чтобы сделать параметры необязательными:

Где Field = @FieldVar OR @FieldVar - это NULL

Вы можете повторить тот же стиль со следующим lambda (пример проверки подлинности):

MyDataContext дБ = новый MyDataContext();

пустота RunQuery(строка параметр1, параметр2 стринг, инт? param3){

Функция checkUser = пользователь =>

((param1.Length > 0)? user.Param1 = = param1 : 1 == 1) &&

((param2.Length > 0)? user.Param2 = = param2 : 1 == 1) &&

((param3 != null)? user.Param3 = = param3 : 1 == 1);

Пользователь foundUser = db.Users.SingleOrDefault(checkUser); }


  Сведения об ответе

prince

14:48, 26th August, 2020

Просто используйте оператор C#'s &&:

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

Правка: Ну, надо читать внимательнее. Вы хотели знать, как условно добавить дополнительные предложения. В таком случае, я понятия не имею. :) Скорее всего, я просто подготовлю несколько запросов и выполню правильный, в зависимости от того, что мне понадобится.


  Сведения об ответе

COOL

09:43, 4th August, 2020

Вы можете использовать внешний метод:

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

...

bool ConditionalCheck( typeofRec input ) {
    ...
}

Это будет работать, но не может быть разбито на деревья выражений, что означает, что Linq-SQL будет выполнять код проверки для каждой записи.

Альтернативно:

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

Это может работать в деревьях выражений, то есть будет оптимизировано значение от Linq до SQL.


  Сведения об ответе

crush

14:48, 2nd August, 2020

Ну, я думал, что вы можете поместить условия фильтра в общий список предикатов:

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

В результате получается список, содержащий "me", "meyou" и "mow".

Вы можете оптимизировать это, сделав foreach с предикатами в совершенно другой функции, которая ORs все предикаты.


  Сведения об ответе

Chhiki

04:06, 20th August, 2020

Вы можете создать и использовать этот метод расширения

public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool isToExecute, Expression<Func<TSource, bool>> predicate)
{
    return isToExecute ? source.Where(predicate) : source;
}


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться