Как вы, вероятно, уже знаете, шаблон спецификации позволит вам отправить фильтр в ваш репозиторий (среди прочих случаев).
Я видел много реализаций для этого.
Обычно люди предоставляют другой метод в интерфейсе спецификации, представляющий дерево выражений, которое должно быть отправлено в Entity Framework:
public interface ISpecification<T>
{
bool IsSpecifiedBy(T item);
Expression<Func<T, bool>> GetPredicate()
}
Хранилище вызовет метод GetPredicate
и передаст его методу Where
в DbSet EF.
Таким образом, вы ограничили, какие выражения будут генерироваться, и гарантируете, что он сгенерирует допустимый оператор SQL.
Чтобы включить логические операторы в спецификации, вам нужно смешать выражения вместе. это сообщение от Владмира Хорикова , где он подробно объясняет, как это сделать.
Мне обычно не нравится это решение, так как оно предполагает, что ваша модель домена совпадает с вашей моделью персистентности . Большинство людей в порядке с этим. Но мне нравится держать вещи ОЧЕНЬ разделенными на луковой архитектуре .
Опытным путем я обнаружил, что в конечном итоге Entity Framework будет загрязнять модель вашего домена с помощью dbcontexts, атрибутов EF, открытых сеттеров, свойств, которые имеют смысл только для базы данных и т. Д.
Поэтому я обычно держу 2 отдельные модели (классы), причем сущность «постоянство» очень проста и очень похожа на схему базы данных, а сущность «домен» обогащена поведением и инвариантами.
И это создает проблему для решения, описанного выше, поскольку спецификация основана на модели предметной области и не может иметь зависимостей для модели постоянства.
Так что вам нужно будет перемещаться по составному спецификации и создавать его для создания предиката. Посетитель - хороший шаблон дизайна для этого.
Я недавно написал серию постов, в которых объясняю