Здравствуйте, 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 на основе созданного для неё фильтра
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))
Но городить подобное ради разовой задачи, имхо, перебор.
Здравствуйте, 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: Как писать подобные запросы не важно, важно чтобы выполнялось эффективно. Т.е. чтобы в бд обращалось один раз.
Привет
Есть приложение .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)
но может есть что-то элегантнее?
Почему так много полей в таблице не спрашивать)
Здравствуйте, 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 — он накатает.