如何将通用存储库与 DDD(域模型 + 持久性模型)一起使用?

How to use Generic Repository with DDD (Domain Model + Persistence Model)?

我有一个问题。我们正在使用通用存储库,我们的领域模型也是持久化模型,但这导致我们对领域模型进行了大量调整以与 ORM 保持一致,例如:- 我们必须放置一个默认的私有构造函数和一些其他脏东西changes ,我们正在使用(Entity Framework 在这种情况下),现在我们决定拥有一个不同于我们丰富的领域模型的持久性模型,但我们不能在这种情况下使用通用存储库。 注意:- 我们使用工厂来创建领域模型,但我们使用 AutoMapper 将领域模型转换为持久性模型。

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

通用存储库模式,被一些人视为 antipattern,可以追溯到早期 DDD 采用,当时人们正在寻找工具和技术来简化 DDD 系统中的持久性。大多数实现最终在通用存储库的合同中公开了 ORM 查询细节(IQueryable 在 Entity Framework 的情况下),因为它们是您可以询问存储库的各种事物之间的方便共同点。

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

如果您仍然绝对肯定 Generic Repository 是通过代码重用获得收益的最佳权衡(我建议首先挑战),Greg Young gives us 是一个合理的中间立场:

So the answer here is to still use a generic repository but to use composition instead of inheritance and not expose it to the domain as a contract.

您可以利用相同的方法并利用该接缝将域模型/持久性模型映射混合在一起。

可能是这样的(未测试):

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