Добавить условие в запрос linq - PullRequest
1 голос
/ 22 сентября 2010

Я создаю слой репозитория для nhibernate, в котором у меня есть следующий метод поиска:

public IList<TEntity> Find(Expression<Func<TEntity, bool>> query)

Я хотел бы добавить условие к запросу в этом методе.Дополнительное условие должно ограничивать строки всем, где RemovedAt больше DateTime.Now.

Объяснение с использованием SQL:

Предположим, у меня есть следующий запрос SQL:

SELECT * FROM users WHERE first_name LIKE 'a%' OR last_name LIKE 'a%'

Это будет выглядеть после изменения:

SELECT * FROM users WHERE (first_name LIKE 'a%' OR last_name LIKE 'a%') AND created_at > '2010-09-22 19:31'

Можно ли это сделать по запросу linq или в nhibernate?

Редактировать

Извините, забыл упомянуть, что у всех сущностей нет метода RemovedAt.Интерфейс объявлен как:

public interface IRepository<TEntity, TKey> where TEntity : class, new()

Я изменяю CreatedAt / RemovedAt / updatedAt (в их соответствующих методах), ища свойство с этим именем и используя отражение для обновления значения.

Ответы [ 2 ]

2 голосов
/ 22 сентября 2010

Прежде всего, я не уверен, почему вы просто не возвращаете IQueryable и позволяете пользователю метода определить, хотят ли они его в виде списка и т. Д. Поскольку IQueryables не выполняются до тех пор, пока они не потребуются, вы можете продолжать добавлять вдерево выражений до тех пор, пока оно вам действительно не понадобится.

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

Если вы действительно хотите сохранить интерфейс как IList вместо IQueryable, просто добавьте дополнительное выражение в дерево выражений перед компиляцией.

Поскольку у меня была ограниченная работа с корневым уровнемдеревья выражений, я бы, скорее всего, неправильно описал синтаксис, поэтому приведу другой пример, который может дать вам достаточно информации о том, о чем я говорю:

var query = something.Where( n => n.FirstName.StartsWith("N")) ;
query = query.Where(n => n.created_at > DateTime.Now);
return query.ToList();

Надеюсь, это имеет смысл.Вы можете просто продолжать добавлять критерии в дерево выражений до тех пор, пока оно не будет скомпилировано и выполнено.

Я все же рекомендовал бы вместо этого передавать arround IQueryable.В моем примере вы просто вернули бы запрос вместо вызова ToList.Это упрощает свободный синтаксис и будет работать лучше с nHibernate, потому что nHibernate будет пытаться учесть все критерии перед вызовом базы данных.Например, если вам нужен только аггрегат или счетчик, он будет обрабатываться в базе данных, а не вытягивать все строки в список, а затем выполнять итерацию по нему, чтобы получить агрегат или счет.

0 голосов
/ 21 февраля 2013

Для тех, кто использует Уровень бизнес-логики поверх своего хранилища вместе с инструментом типа AutoMapper для сопоставления объектов передачи данных и моделей сущностей, используйте Predicate Builder из LinqKit , чтобы позволить вашим контроллерам MVC / API добавлять дополнительные фильтры System.Linq.Expressions.Expression к фильтрам по умолчанию, установленным в бизнес-компонентах.

Использование построителя предикатов позволит динамическиизмените ваш IQueryable перед отправкой в ​​AutoMapper для сглаживания, т.е. внесения списка в память.

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