Строго говоря, репозиторий предлагает семантику коллекции для получения/размещения объектов домена. Он обеспечивает абстракцию вокруг вашей реализации материализации (ORM, ручная прокатка, макет), чтобы потребители объектов домена были отделены от этих деталей. На практике репозиторий обычно абстрагирует доступ к объектам, то есть к объектам домена с идентификатором и обычно к постоянному жизненному циклу (в аромате DDD репозиторий обеспечивает доступ к совокупным корням).
Минимальный интерфейс для хранилища выглядит следующим образом:
void Add(T entity);
void Remove(T entity);
T GetById(object id);
IEnumerable<T> Find(Specification spec);
Хотя вы увидите разницу именования и добавление Save/SaveOrUpdate семантики, выше, является «чистой» идеей. Вы получаете элементы добавления/удаления ICollection и некоторые искатели.Если вы не используете IQueryable, вы также увидите методы поиска в хранилище, как:
FindCustomersHavingOrders();
FindCustomersHavingPremiumStatus();
Есть две связанные проблемы с использованием IQueryable в этом контексте. Во-первых, это возможность утечки деталей реализации клиенту в виде отношений объекта домена, т. Е. Нарушений Закона Деметры. Во-вторых, репозиторий получает нахождение обязанностей, которые могут не принадлежать надлежащему репозиторию объектов домена, например, поиск прогнозов, которые меньше запрашиваемого объекта домена, чем соответствующие данные.
Кроме того, использование IQueryable «прерывает» шаблон: репозиторий с IQueryable может предоставлять или не предоставлять доступ к «объектам домена». IQueryable предоставляет клиенту множество опций о том, что будет реализовано при окончательном выполнении запроса. Это основная идея дебатов об использовании IQueryable.
Что касается скалярных значений, вы не должны использовать репозиторий для возврата скалярных значений. Если вам нужен скаляр, вы обычно получаете это от самого объекта. Если это звучит неэффективно, это возможно, но вы можете не заметить, в зависимости от ваших характеристик нагрузки/требований. В случаях, когда вам нужны альтернативные виды объекта домена, из-за причин производительности или из-за необходимости объединять данные со многих объектов домена, у вас есть два варианта.
1) Используйте репозиторий объекта, чтобы найти указанные объекты и проект/карту в сплющенном виде.
2) Создайте интерфейс поиска, предназначенный для возврата нового типа домена, который инкапсулирует сглаженное представление, которое вам нужно. Это не будет репозиторий, потому что семантики коллекции не будет, но она может использовать существующие репозитории под обложками.
Одна вещь, которую следует учитывать, если вы используете «чистый» репозиторий для доступа к постоянным объектам, заключается в том, что вы нарушаете некоторые преимущества ORM. В «чистой» реализации клиент не может предоставить контекст того, как будет использоваться объект домена, поэтому вы не можете указать репозиторий: «Эй, я просто собираюсь изменить свойство customer.Name, так что don «Не волнуйся, чтобы получить эти загруженные ссылки». С другой стороны, вопрос заключается в том, должен ли клиент знать об этом. Это обоюдоострый меч.
Что касается использования IQueryable, большинству людей кажется комфортно «разбивать» шаблон, чтобы получить преимущества динамической составы запросов, особенно для клиентских обязанностей, таких как пейджинг/сортировка. В этом случае, вы можете иметь:
Add(T entity);
Remove(T entity);
T GetById(object id);
IQueryable<T> Find();
, а затем вы можете избавиться от всех этих пользовательских методов поиска, которые действительно загромождают репозиторием по мере роста потребностей запросов.
Я столкнулся с сообщением jbogard на эту тему сегодня: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/09/02/ddd-repository-implementation-patterns.aspx – pfries
+1: ". .. Кажется, что людям очень удобно «ломать» шаблон, чтобы получить преимущества динамической композиции запросов ... » –