Привет
Есть приложение .net + mssql и есть таблица с 50 полями и нужно сделать выборку из этой таблицы на основании фильтра который состоит из 15 параметров (поля этой таблицы)
Можно конечно сделать перебор всех параметров фильтра типа
if (filter.Param1 != null)
context.Entities.Where(a => a.Param1 = filter.Param1)
if (filter.Param2 != null)
context.Entities.Where(a => a.Param2 = filter.Param2)
но может есть что-то элегантнее?
Почему так много полей в таблице не спрашивать)
P>P>if (filter.Param1 != null)
P> context.Entities.Where(a => a.Param1 = filter.Param1)
P>if (filter.Param2 != null)
P> context.Entities.Where(a => a.Param2 = filter.Param2)
P>
Вполне нормальный вариант.
Простой в реализации, понятный в поддержке и легко расширяемый (скажем, по условиям вида !=, contains, starts with и т.п.)
Можно, конечно, заморочиться и родить что-то такое:
public static Expression<Func<Entity, bool>> BuildFilterExpression(Filter filter) {
// TODO:
// рефлексией вытягиваем из filter все не null-свойства
// и в предположении, что имя свойства в фильтре = имя свойства в Entity, собираем нужный Expression
}
// Тогда будет так:
context.Entitites.Where(BuilFilterExpression(filter))
Но городить подобное ради разовой задачи, имхо, перебор.
Здравствуйте, RushDevion, Вы писали:
P>>P>>if (filter.Param1 != null)
P>> context.Entities.Where(a => a.Param1 = filter.Param1)
P>>if (filter.Param2 != null)
P>> context.Entities.Where(a => a.Param2 = filter.Param2)
P>>
RD>Вполне нормальный вариант.
RD>Простой в реализации, понятный в поддержке и легко расширяемый (скажем, по условиям вида !=, contains, starts with и т.п.)
RD>Можно, конечно, заморочиться и родить что-то такое:
RD>RD>public static Expression<Func<Entity, bool>> BuildFilterExpression(Filter filter) {
RD> // TODO:
RD> // рефлексией вытягиваем из filter все не null-свойства
RD> // и в предположении, что имя свойства в фильтре = имя свойства в Entity, собираем нужный Expression
RD>}
RD>// Тогда будет так:
RD>context.Entitites.Where(BuilFilterExpression(filter))
RD>
RD>Но городить подобное ради разовой задачи, имхо, перебор.
У нас используется второй вариант, часть которого писал я. А так я вообще за первый всегда, потому что он проще. Если лень самому писать много if, то можно попросить capilot — он накатает.
Здравствуйте, peer, Вы писали:
P>Привет
P>Есть приложение .net + mssql и есть таблица с 50 полями и нужно сделать выборку из этой таблицы на основании фильтра который состоит из 15 параметров (поля этой таблицы)
P>Можно конечно сделать перебор всех параметров фильтра типа
P>P>if (filter.Param1 != null)
P> context.Entities.Where(a => a.Param1 = filter.Param1)
P>if (filter.Param2 != null)
P> context.Entities.Where(a => a.Param2 = filter.Param2)
P>
Я не эксперт по EF, но код выглядит некорректным.
Вы, наверное, имели в виду что-то вроде:
var source = context.Entities;
if (filter.Param1 != null)
source = source.Where(a => a.Param1 = filter.Param1);
if (filter.Param2 != null)
source = source.Where(a => a.Param2 = filter.Param2);
...
Это вполне себе элегантно. Более элегантные вещи потребуют метапрограммирования, и оправданы тогда, когда у вас есть более-менее сложная модель. Например, у вас таких таблиц по 15 полей — много, и поддерживать вручную все вот эти N*M
if (filter.StartDate != null) становится трудно. Тогда можно навелосипедить кодогенерацию, которая
1. Порождает классы фильтров для каждой Entity
2. Порождает код по генерации предиката для Entity на основе созданного для неё фильтра
Здравствуйте, Sinclair, Вы писали:
S>Я не эксперт по EF, но код выглядит некорректным.
S>Вы, наверное, имели в виду что-то вроде:
S>S>var source = context.Entities;
S>if (filter.Param1 != null)
S> source = source.Where(a => a.Param1 = filter.Param1);
S>if (filter.Param2 != null)
S> source = source.Where(a => a.Param2 = filter.Param2);
S>...
S>
Если уж совсем быть корректным, тогда source = source.Where(a => a.Param1
== filter.Param1)
PS: Как писать подобные запросы не важно, важно чтобы выполнялось эффективно. Т.е. чтобы в бд обращалось один раз.