【问题标题】:To Repository or Not To Repository到存储库或不到存储库
【发布时间】:2014-04-29 11:05:16
【问题描述】:

当我第一次了解领域驱动设计时,我还被介绍了存储库和工作单元模式,这些模式曾经似乎是那些像穴居人一样向数据库抛出 SQL 查询的酷孩子们的一流模式。我越深入该主题,我就越了解它们似乎不再是必需的,因为像 EFNHibernate 这样的 ORM将工作单元和存储库实现到一个 API 中,称为会话或上下文。

现在我不确定该怎么做。到存储库或不存储库。我真的理解这样的论点,即这种泄漏的抽象只会使事情过于复杂,而绝对没有添加任何可以简化数据访问的内容,但是,将我的应用程序的每个可能方面与例如实体框架。通常,我遵循一些简单的准则:

  1. 领域层是系统的核心,包含实体、服务、存储库...
  2. 基础设施层提供基础设施关注领域接口的实现,例如文件、数据库、协议..
  3. 应用层托管一个组合根,用于连接和协调所有内容。

我的解决方案通常如下所示:

Domain.Module1
Domain.Module2
    IModule2Repo
    IModule2Service
    Module2
Infrastructure.Persistence
    Repositories
        EntityFrameworkRepositoryBase
MyApp
    Boostrapper
        -> inject EntityFrameworkRepositoryBase into IRepository etc.

我使用IRepository<'T> 保持我的域层清洁,这也是一个域问题,不依赖于告诉我如何访问数据的任何其他内容。当我现在要对需要数据访问的IModule2Service 进行具体实现时,我将不得不注入DbContext 并由此将其直接耦合到基础设施层。 (来到 Visual Studio 项目,由于循环依赖,这最终会变得非常棘手!

另外存储库混杂的作品有什么替代品? CQRS?如何抽象出一个纯粹的基础设施框架?

【问题讨论】:

    标签: c# entity-framework dependency-injection domain-driven-design repository-pattern


    【解决方案1】:

    “存储库”哈哈……

    无论如何,您不希望域耦合到 EF,这就是为什么您的存储库界面中的 T 应该是 域聚合根 和 不是 EF 实体(或旨在与 EF 一起正常工作的“域”对象)。

    您的领域层永远不会与持久性耦合,因为它只知道抽象。当 Module2Service 需要数据访问时,它要么使用 DAO(或存储库 - 不一定是 DDD 版本 - 如果它有意义的话)或者服务本身是在 DAL 中实现的(如果它不包含业务逻辑)。

    在您的情况下,最好的方法可能是 DAO/存储库,它当然会“隐藏”EF 部分。如果您似乎编写了太多代码,那么您实际上并没有,我认为保持适当的关注点分离比节省 50 LoC(整整 5-10 分钟)更重要。

    CQRS 始终是具有丰富域的好主意,但作为任何解决方案,它都有一个缺点,即它需要更多代码(而且我知道每个编码器在定义上都是懒惰的,但我们需要做一些“他妈的”工作,一个应用程序不会自己构建,一个可维护的应用程序在开始时甚至更多工作)。 如果通过抽象一个纯粹的基础架构框架意味着隐藏 EF,那么存储库是您最好的选择,您甚至不必将类命名为“存储库”,这是重要的原则,这就是存储库所做的:为域抽象持久性.

    【讨论】:

    • "为什么存储库接口中的 T 应该是域聚合根而不是 EF 实体" -> 我从来没有这样想过。这改变了一切!
    猜你喜欢
    • 2020-09-12
    • 2017-12-02
    • 2012-08-14
    • 2015-09-25
    • 2013-12-11
    • 1970-01-01
    • 2020-10-14
    • 2020-10-24
    • 2012-08-11
    相关资源
    最近更新 更多