如何使用带有DDD的通用存储库(域模型+持久性模型)?

ror*_*012 3 c# domain-driven-design ddd-repositories repository-pattern entity-framework-6

我有个问题.我们正在使用通用存储库,我们的域模型也是持久性模型,但这导致我们调整我们的域模型以与ORM对齐,例如: - 我们必须放置默认的私有构造函数和其他一些脏的更改,我们正在使用(在这种情况下为Entity Framework),现在我们决定使用与我们的富域模型不同的持久性模型,但在这种情况下我们不能使用Generic Repository.注意: - 我们使用工厂来创建我们的域模型,但我们使用AutoMapper将域模型转换为持久模型.

gui*_*e31 6

这是一个棘手的问题,因为你正试图调和两种对立的DDD持久性方法,这些方法是由相反的思想流派设计的.

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

最近的持久性模型方法是朝着相反方向迈出的一步 - 远离ORM.你所做的是引入一个额外的间接层,正是为了让你的域模型(也包括Repository接口)没有被持久层特定的东西所污染.

如果你仍然绝对肯定Generic Repository是你通过代码重用获得的最佳权衡(我建议首先挑战),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; }
}
Run Code Online (Sandbox Code Playgroud)