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

时间:2016-11-14 08:05:43

标签: c# entity-framework-6 domain-driven-design repository-pattern ddd-repositories

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

1 个答案:

答案 0 :(得分:5)

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

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

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

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

  

所以这里的答案是仍然使用通用存储库但要使用   组合而不是继承,而不是将其暴露给域   合同。

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

这些方面的某些内容可能(未经测试):

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