LINQ, Большой фильтр по запросу - PullRequest
3 голосов
/ 29 января 2009

Я создаю раздел приложения, который вращается вокруг извлечения информации о транзакциях из базы данных. Из-за характера данных в таблице есть много столбцов, по которым я хочу фильтровать. У меня есть поле выбора фильтра с 15 полями, которое я хочу иметь возможность создать предложение where для оператора LINQ. Интересная часть приходит, когда я хочу, чтобы определенные поля были нулевыми. Например, я хочу иметь возможность фильтрации по любому или всем из:

  • Тип транзакции
  • Код ответа
  • Сумма сделки
  • Многие другие

Я могу создать предикат, который выглядит как

Func<Transaction, bool> pred = t => t.ResponseCode == ResponseCode && t.TransactionType == TransactionType && t.TransactionAmount > 100.00;

Но чтобы иметь возможность выбирать, какие поля включать в предикат, я объединяю предикаты вместе:

Func<Transaction, bool> pred = t => true;
if(ResponseCode != null)
   pred.AndAlso(t => t.ResponseCode == ResponseCode);
// Rinse and repeat

А затем передать этот предикат предложению where оператора LINQ.

Это работает именно так, как я хочу, но довольно сложно. Есть ли другие способы сделать это?

UPDATE: Спасибо правосудию за комментарии. Я не использую LINQ to SQL, я использую LINQ для коллекции объектов из хранилища. Как бы вы программно построили фильтр Expression?

Ответы [ 2 ]

8 голосов
/ 30 января 2009
  • В динамическом SQL ... Поскольку у вас есть только одно предложение WHERE - вы должны объединить предикаты с помощью AND.
  • В построении запросов linq ... вы получаете столько предложений WHERE, сколько хотите. Linq будет И их вместе для вас при переводе запроса.

Пример:

IQueryable<Transaction> query = db.Transactions;

if (filterByTransactionType)
{
  query = query.Where(t => t.TransactionType == theTransactionType);
}
if (filterByResponseCode)
{
  query = query.Where(t => t.ResponseCode == theResponseCode);
}
if (filterByAmount)
{
  query = query.Where(t => t.TransactionAmount > theAmount);
}

Другой пример:

List<Expression<Func<Transaction, bool>>> filters = GetFilterExpressions();

IQueryable<Transaction> query = db.Transactions;
filters.ForEach(f => query = query.Where(f));
0 голосов
/ 29 января 2009

Во-первых, вам нужно будет использовать Expression<Func<Transaction, bool>> для LINQ-to-SQL (это то, что вы пытаетесь использовать, и это не то же самое, что LINQ).

Во-вторых, вы можете программно создать Expression<Func<Transaction, bool>>, используя пространство имен System.Linq.Expression.

Вы не сможете использовать LINQ как таковой для запроса базы данных с помощью программно построенных выражений. Вместо использования операторов запроса вам нужно будет использовать методы расширения запроса: например, вместо from p in db.People where p.Age > 50 select p.Name вам нужно будет использовать db.People.Where(p => p.Age > 50). Вы можете использовать этот стиль для добавления фильтров: db.People.Where(myFilter), где myFilter = new Expression<Func<Person, bool>>(p => p.Age > 50). В вашем случае myFilter будет вашим программно встроенным фильтром, а не фильтром, созданным с использованием синтаксиса лямбда-выражений.

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