在 Clean Architecture 和 DDD 中使用单个数据库执行命令和查询来实现复杂查询的位置

问题描述 投票:0回答:1

我试图遵循干净的架构原则,当我尝试将有关持久性的实现细节保留在应用程序核心之外时:

  1. 存储库接口位于应用程序核心项目中
  2. Application Core 项目未引用任何数据访问库(ORM)
  3. Infrastracture 项目引用 ORM 并实现存储库

(参考解决方案这里

但是,我很难处理数据库查询,例如:

向我提供逾期未结订单以及客户详细信息和总价格。

因为这样的疑问

  1. 包含一些业务逻辑(订单被视为开放,当......,。逾期是当......)
  2. 通常必须针对性能进行优化(例如,不获取订单商品,而是获取订单商品价格的总和)。

我将

OpenOrdersQuery
dto 放在应用程序核心层,但是我在哪里实现它的处理程序?

如果我在

Infrastructure
项目中实现它,我会在那里放置一些业务逻辑

我无法在应用程序核心中实现它,因为没有直接的数据访问

.net architecture domain-driven-design cqrs clean-architecture
1个回答
0
投票

如果我在基础设施项目中实施它,我就会投入一些业务 逻辑在那里

其实不然。您的域模型确实负责业务逻辑(从命令端),如果这泄漏到应用程序/基础设施层,那么这就是应该解决的问题。

但是,您现在正在查看 CQRS 的查询端。理想情况下,您应该拥有一个针对用例处理(命令)优化的数据库和一个针对读取端(查询)优化的数据库。但是,作为替代,您可以使用相同的数据库进行写入和读取。我经常这样做作为第一步,然后在性能需要时迁移到读取优化的仓库和/或我清楚可以执行哪些查询以有效地设计读取端数据库。

即使使用单个数据库来执行命令和查询,我也不会使用 ORM 来执行查询。我会直接用SQL查询数据库。这可以避免您遇到的问题,即您的存储库方法(为命令设计)可能会检索与正在执行的查询无关的相关数据。

所以,总结一下:

命令管道

  • 客户端创建命令
  • 客户端发送命令到命令模块,命令模块找到处理程序来执行命令
  • 处理程序使用域模型(又名命令模型)来处理命令用例的业务逻辑,然后可以使用存储库接口添加实体。
  • 基础设施存储库实现会将实体添加到 ORM 中的工作单元。

查询管道

  • 客户端创建查询
  • 客户端将查询发送到查询模块,查询模块找到处理程序来执行查询。
  • Handler创建SQL语句,打开数据库连接并直接查询。 (它不会为此使用您的域模型)。
  • Handler 将结果映射到所需的 DTO 以供客户端使用。

是的,从一个角度来看,当没有特定的布尔值“OrderIsOpen”时,知道什么是“Open”订单可以被视为业务逻辑,但它不是命令业务逻辑(应保留在域模型中)。

在某个阶段,如果您确实设置了一个针对客户端可能执行的查询进行优化的读取数据库,那么在填充该数据库期间(在命令完成之后),您可能会考虑使用数据库中的“OrderIsOpen”字段来进行查询性能更高,并且查询处理程序无需知道哪些其他属性表明订单已打开。

© www.soinside.com 2019 - 2024. All rights reserved.