Я использую случайно сгенерированные фонетически звучащие пароли для одного веб-приложения, которое я написал. В итоге я жестко запрограммировал список «грязных» слов, которые неприемлемы, но список, соответствующий моему шаблону, оказался довольно коротким.
Интересная проблема, и я уверен, что вы не первый, кто столкнулся с ней (а у меня возникли проблемы).
Для меня реальный вопрос: где вы хотите разместить свою логику нетерпеливой загрузки?
Вне репозитория в клиентском коде
var product = productRepository
.With(x=>x.Customer)
.With(x=>x.Price)
.With(x=>x.Manufacturer)
.GetById(id);
Я не думаю, что это хороший программный дизайн: похоже, это может вызвать «смерть от тысячи сокращений», если такие конструкции будут разбросаны по всему вашему приложению.
Или в репозитории . Пример:
interface IProductRepository {
Product GetById(int id);
Product GetByIdWithCustomers(int i);
}
Итак, ваш клиентский код будет выглядеть так:
var product = productRepository.GetByIdWithCustomers(id);
Обычно я создаю один BaseRepository, в котором определены только базовые операции CRUD:
public class BaseRepository<TEntity, TPrimaryKey> {
public void Save(TEntity entity) { ... }
public void Delete(TEntity entity) { ... }
public TEntity Load(TPrimaryKey id) { ... } // just gets the entity by primary key
}
Затем я расширяю этот базовый класс / интерфейс, чтобы предоставить определенные методы для выборки объекты домена. Ваш подход, кажется, идет в несколько похожем направлении.
public class MediaRepository : BaseRepository<Media, int> {
public long CountMediaWithCategories() { ... }
public IList<Media> MediaInCategories(IList<Category> categories) { .... }
}
Хорошая новость: все, что связано с ORM (жадная загрузка конфигурации, глубина выборки и т. д.) инкапсулируется в классе Repository, клиентский код просто получает набор результатов.
Я пробовал работать с очень общими репозиториями, как это пытаетесь сделать вы, но в основном закончил тем, что написал конкретные запросы и репозитории для моих объектов домена.
Я понимаю, что вы пытаетесь сделать, но вы несколько выходите за рамки основного шаблона репозитория.
Минимальный интерфейс репозитория может включать методы для:
Если вы добавите к этому дополнительные методы, вы начнете сталкиваться с ситуациями, когда интерфейс не обязательно имеет смысл для всех ваших совокупных корней.
Иногда просто невозможно иметь полностью красивый API. Если то, что у вас есть, работает «достаточно хорошо» для вас, я бы согласился с этим. Если вам нужно уйти от шаблона репозитория, чтобы предоставить лучший API для программирования, сделайте это!
Шаблон репозитория не является комплексным решением. Иногда нужно другое решение.
var product = productRepository
.With(x=>x.Customer)
.With(x=>x.Price)
.With(x=>x.Manufacturer)
.GetById(id);
Я понимаю ваше желание определить глубину запроса графа объекта, как указано выше, но я думаю, что есть более простой способ сделать это. Как насчет того, чтобы вместо выбора возврата продукта (с указанием клиента, цены и производителя) по идентификатору, я просто возвращаю продукт - и все эти другие вещи являются ленивыми загруженными свойствами продукта?
Я добиваюсь этой «полной доступности графика» путем "цепочка" объектной модели POCO на моем уровне доступа к данным. Таким образом, мне не нужно знать, сколько загруженных данных нужно вытащить за один раз, я просто спрашиваю, что мне нужно, из графа объектов, и модель знает, что загружено, а что требует дополнительного восстановления из DAL. Взгляните на эти три ответа - я пытаюсь объяснить там свой подход.