【问题标题】:How to use Generic Repository with DDD (Domain Model + Persistence Model)?如何将通用存储库与 DDD(域模型 + 持久性模型)一起使用?
【发布时间】:2017-03-27 19:47:37
【问题描述】:

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

【问题讨论】:

  • “在这种情况下我们不能使用通用存储库” - 为什么?为什么首先需要它?
  • 你好,我需要它来简化开发过程
  • 我不需要在每个存储库中重复相同的代码
  • 你不想重复哪些代码,你是如何实现的,为什么它与持久性模型不兼容?也看看blog.sapiensworks.com/post/2012/03/05/…
  • 例如,接受谓词的通用查询

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


【解决方案1】:

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

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

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

如果您仍然绝对肯定 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; }
}

【讨论】:

  • 感谢您的出色解决方案
  • 我还有一个问题。如何以这种新方式使用规范模式
  • 注意,规范是领域模型行为,不是持久性的
  • 我猜你需要一个 Func&lt;Foo, bool&gt;Func&lt;FooPersistence, bool&gt; 的映射器。
  • 你能举个例子澄清一下吗?
猜你喜欢
  • 2012-12-11
  • 2021-02-14
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 2014-02-03
  • 2017-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多