如何使用DDD(域模型+持久化模型)的通用存储库

本文关键字:模型 存储 DDD 何使用 持久化 | 更新日期: 2023-09-27 18:17:42

我有一个问题。我们使用一个通用的存储库和域模型也是持久性模型,但让我们调整我们的域模型与ORM是一致的,例如:——我们必须把一个默认私有构造函数和其他一些肮脏的变化,我们正在使用(实体框架),现在我们决定有一个持久性模型不同于我们的富领域模型但是我们不能使用通用存储库。注意:- 我们使用工厂来创建我们的领域模型,但我们使用AutoMapper从领域模型转换到持久性模型

如何使用DDD(域模型+持久化模型)的通用存储库

这是一个困难的问题,因为您正试图调和DDD中由对立思想学派设计的两种对立的持久性方法。

通用存储库模式,被一些人认为是一种反模式,可以追溯到早期的DDD采用,当时人们正在寻找工具和技术来简化DDD系统中的持久性。大多数实现最终在通用存储库的契约中暴露ORM查询细节(在实体框架的情况下是IQueryable),因为它们是您可以向repo询问的各种事情之间的方便共同点。

最近的持久性模型方法是朝着相反的方向迈出的一步——远离ORM。您所做的是引入额外的间接层,精确地使您的域模型(也包括存储库接口)不受持久性层特定内容的污染。

如果您仍然绝对肯定通用存储库是通过代码重用获得的最佳权衡(我建议首先挑战),Greg Young给了我们一个合理的中间立场:

所以这里的答案是仍然使用通用存储库,但是使用组合而不是继承,并且不将其公开给域一份合同。

您可以利用相同的方法并利用该接缝将域模型/持久模型映射扔到混合中。

可能是以下内容(未测试):

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; }
}