У меня есть вопрос. мы используем общий репозиторий, и наша модель предметной области также является моделью персистентности, но это заставило нас сильно настроить нашу модель предметной области, чтобы она была согласована с ORM, например: - Мы должны поместить частный конструктор по умолчанию и некоторые другие грязные изменений, мы используем (в данном случае Entity Framework), и теперь мы решили использовать модель сохранения, которая отличается от нашей модели расширенной предметной области, но мы не можем использовать общий репозиторий в этом случае. Примечание. - Мы используем фабрики для создания моделей предметной области, но мы используем AutoMapper для преобразования моделей предметной области в модель сохраняемости.
Как использовать общий репозиторий с DDD (модель домена + модель сохраняемости)?
Ответы (1)
Это сложный вопрос, потому что вы пытаетесь примирить два антагонистических подхода к настойчивости в DDD, которые были разработаны противоположными школами.
Шаблон Generic Repository, который некоторые считают antipattern, восходит к раннему принятию DDD, когда люди искали инструменты и методы для упрощения персистентности в системах DDD. Большинство реализаций в конечном итоге раскрывают особенности запросов ORM (IQueryable
в случае Entity Framework) в контракте общего репозитория, потому что они были удобной точкой соприкосновения между всевозможными вещами, которые вы могли запросить в репо.
Более поздний подход модели персистентности - это шаг в противоположном направлении - от ORM. Что вы делаете, так это вводите дополнительный уровень косвенности, чтобы оставить вашу модель предметной области (которая также включает интерфейсы репозитория) незапятнанной специфическими вещами уровня сохраняемости.
Если вы по-прежнему абсолютно уверены, что общий репозиторий - это лучший компромисс для вас с точки зрения выгоды от повторного использования кода (что я бы рекомендовал в первую очередь оспорить), Грег Янг дает нам разумную золотую середину:
Итак, ответ здесь - по-прежнему использовать общий репозиторий, но использовать композицию вместо наследования и не предоставлять его домену в качестве контракта.
Вы можете использовать тот же подход и воспользоваться этим швом, чтобы добавить в микс отображение модели предметной области / модели персистентности.
Возможно, что-то в этом роде (не проверено):
public class FooRepository
{
private PersistenceRepository<FooPersistence> _innerRepository;
public Foo GetFooById(int id)
{
return MapToDomain(_innerRepository.GetById(id));
}
public void Add(Foo foo)
{
_innerRepository.Add(MapToPersistence(foo));
}
public IEnumerable<Foo> GetByCity(string city)
{
return _innerRepository.Find(f => f.City == city).Select(MapToDomain);
}
private Foo MapToDomain(FooPersistence persistenceModel)
{
// Mapping stuff here
}
private FooPersistence MapToPersistence(Foo foo)
{
// Mapping stuff here
}
}
public class PersistenceRepository<T> where T : PersistenceModel
{
public T GetById(int id)
{
//...
}
public void Add(T t)
{
//...
}
public IQueryable<T> Find(Func<T, bool> predicate)
{
//...
}
}
public abstract class PersistenceModel
{
}
public class FooPersistence : PersistenceModel
{
public string City { get; set; }
}
Func<Foo, bool>
к Func<FooPersistence, bool>
.
- person guillaume31; 17.11.2016
Find(FooSpecification spec)
метод, который вызывает Find(FooPersistenceSpecification(spec)
во внутреннем репо?
- person guillaume31; 17.11.2016
Specification<Foo>
в Specification<FooPersistence>
. Это возможно, если проанализировать предикат или унаследовать модель предметной области и модель персистентности от одного и того же класса. В этот момент все становится довольно запутанным. Лучше избегать общих спецификаций в репозиториях домена и оставить их к внутреннему постоянному репо ИМО.
- person guillaume31; 18.11.2016