Вопрос: Linq-to-SQL, объединяющий два выражения > ("where where") с и / или


Во-первых, я должен сказать, что я прочитал несколько сообщений об этом в StackOverflow, но я не могу получить желаемый результат.

Позвольте мне объяснить контекст (упрощенный): я использую Linq-to-SQL для запросов клиентов с недавними посещениями магазина и (необязательно) получить только те, у кого определенная сумма платежей. Предположим, у меня есть модель с классами клиентов, посещений и платежей.

Итак, сосредоточив внимание на Where Я пытаюсь это сделать:

Expression<Func<Entityes.Clients, bool>> filter = null;

filter = c => 
          c.Visits.Any(v => v.VisitDate > DateTime.Now.Date.AddMonths(-(int)visitsSince));


if (minPayment.HasValue && minPayment.Value > 0)
{
     filter.And(
               c => c.Payments.Sum(p => p.Quantity) > minPayment.Value);
}

filter.And метод является методом расширения, рекомендованным на этом форуме, ниже вы можете увидеть определение:

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1,
                                            Expression<Func<T, bool>> expression2)
{
  InvocationExpression invokedExpression =
      Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());

  return Expression.Lambda<Func<T, bool>>
      (Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
}

Однако это не работает для меня, как ожидалось, и результаты не фильтруются по сумме платежа. Нет ошибки в использовании данных или модели linq-to-sql, поскольку этот код работает нормально:

filter = c => 
           c.Visits.Any(v => v.VisitDate > DateTime.Now.Date.AddMonths(-(int)visitsSince)))
             && c => c.Payments.Sum(p => p.Quantity) > minPayment.Value;

Тем не менее, я не хочу использовать последний код, потому что у меня есть несколько более сложных сценариев, в которых мне нужно поэтапно создавать выражение фильтра с комбинацией «и / или» каждой части.

PD: Я парень из ADO.Net DataSets, который пытается изучить Linq-to-SQL и вскоре Entity Framework, я надеюсь, что это будет полезно для сообщества StackOverflow.


5


источник


Ответы:


Вы не назначаете результат Andни к чему.

Я полагаю, что соответствующая часть вашего кода должна выглядеть следующим образом:

if (minPayment.HasValue && minPayment.Value > 0)
{
   filter = filter.And(
            c => c.Payments.Sum(p => p.Quantity) > minPayment.Value);
}

Дело в том, что ваш (или SO, как вы упомянули) And функция возвращается  выражение, содержащее конъюнкцию двух выражений. Он не изменяет объект, на который он вызывается.


3



Проблема в этой строке:

filter.And(c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 

And метод возвращает другой делегат, который вы никому не назначили. Попробуй это:

filter = filter.And(c => c.Payments.Sum(p => p.Quantity) > minPayment.Value); 

Просто для уточнения, And это метод, который принимает два выражения и объединяет их логику для создания нового выражения. Он не изменяет выраженное выражение, но возвращает новое выражение как возвращаемое значение. Поэтому в коде, который вы вызываете filter.And(...) но ничего не делает с возвращаемым значением, поэтому filter все еще ссылается на исходное лямбда-выражение.


1



Проверьте LinqKit и класс PredicateBuilder: http://www.albahari.com/nutshell/predicatebuilder.aspx


0