Linq-to-SQL объединяет два выражения> («где пункт») с и / или - PullRequest
5 голосов
/ 22 февраля 2012

Во-первых, я должен сказать, что я прочитал несколько постов об этом в 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.

Ответы [ 3 ]

3 голосов
/ 22 февраля 2012

Вы никому не присваиваете результат And.

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

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

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

1 голос
/ 22 февраля 2012

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

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 по-прежнему ссылается на исходное лямбда-выражение.

0 голосов
/ 22 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...