【问题标题】:DDD Repository vs Factory, Am I rehydrating or creating?DDD 存储库与工厂,我是在补水还是创建?
【发布时间】:2021-08-31 00:27:39
【问题描述】:

我们有一个外部拥有的 SQL 服务器,其中的数据需要定期移植到我们的团队拥有的 (SQL) 服务器中。

外部和内部服务器共享相同的域概念,但以非常不同的形式存在。将对象从其外部形式转换为我们自己的领域形式是一个复杂的过程。

目前这样做是这样的:

  1. Adapter 查询 External Db,使用 Automapper 映射到 DTO(Adapter 位于底层)
  2. 适配器将DTO返回给应用层(DTO在应用层中定义)
  3. 工厂从 DTO 构造域对象并工厂加载相关的域聚合以设置导航 ID + 其他属性(工厂位于应用层)

将工厂在这里的工作视为真正构建一个新对象是否正确,因为它实际上是从外部来源为对象补水,并且我们添加了更多(必需的)装饰?实体 ID 与其转换后的 ID 保持一致。

但是,将其称为存储库也感觉不对,因为除了从单个数据库中进行简单的水合之外,还有更多的工作?

我还是 DDD 的新手,因此感谢所有输入!

【问题讨论】:

  • 为什么要写代码来做数据导入?为什么不使用 BCP 之类的东西?更快、更简单。
  • 实际上有大约 30 个外部 SQL 服务器具有我们从中提取的相同数据库架构。有逻辑进入哪个服务器子集(或所有服务器)适合在给定时间点导入。我们觉得像 BCP 这样的选项没有提供所需的灵活性或长期可扩展性。此外,我们仍然需要 c# 代码来完成数据导入后的水合。水合和输入需要在同一阶段发生,以防止我们的数据库中存在无效数据

标签: c# domain-driven-design ddd-repositories hexagonal-architecture


【解决方案1】:

您的流程基本上是缺少一层并且具有过多的映射。你应该只有 3 个数据模型:

  • 源数据库模型
  • 领域模型
  • 目标数据库模型

您的源和目标数据库模型是实体(在 EF 的意义上,而不是 DDD)。它们已经是 POCO/DTO,您无需在将它们转换为领域模型之前将它们映射到中间模型。

您的应用程序应该做的是:

  • 从源数据库读取
  • 将 EF 实体转换为域模型
  • 验证一些业务规则
  • 将域模型转换为目标 EF 实体
  • 写入目标数据库

为了做到这一点,我建议您创建一个额外的“合同”层,您可以在其中放置 EF 模型的程序集。每个数据库都应该有一个程序集。我强烈建议使用 EF 数据库优先工具生成这些。这些程序集将仅包含具有用于数据库读/写操作的 db 上下文的 EF 模型,并且可以被视为外部服务合同。

您的适配器层现在基本上将充当域层和合同层之间的转换层。它们主要由地图或工厂以及存储库组成。如果任何数据库发生变化,您可以简单地重新生成关联的合同程序集并更新任何受影响的适配器程序集(除非该变化意味着领域模型的演变)。

您的入口点将能够通过调用源适配器存储库来导入您的数据,这将查询源数据库并将结果自动映射到域对象,然后验证您的业务规则,最后调用目标适配器存储库,它将写入将域对象自动映射到目标 EF 实体后的目标数据库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 2013-02-19
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多