domain-driven-design - DDD - 在单个存储库方法中查询多个聚合的自定义 SQL 怎么样?
问题描述
我设计我的聚合来强制执行不变量和业务规则。我总是将我的聚合视为“写入模型”/“交易模型”。
考虑到这一点,我总是可以使用自定义 SQL/Linq 在我的存储库中公开“复杂”的 GET 方法,因为我不会更改数据。
例如,考虑两个虚构的聚合根(学生和学校),它们之间仅使用参考 ID。如果我想向学校的所有学生发送电子邮件,出于性能目的,我通常会使用执行此操作的域服务:
- 使用“GetAllStudentEmailAddressesForSchool(Guid schoolId)”之类的方法调用存储库
- 为每个学生发送一封电子邮件
当然,存储库实现需要对两个聚合执行“复杂”查询 (JOIN)。
典型的替代方法是在域服务中协调对存储库的多个调用:
- 从 ISchoolRepository 获取学校
- Foreach 学校的 StudentId,调用 IStudentRepository
(当然这取决于聚合建模,但基本概念仍然存在)。
我与同事对此进行了很多辩论,许多人认为第一种方法会在域之外(也就是在基础设施层,在存储库实现中)泄漏域业务。
对我来说,这是一个简单的过滤策略,就像 ISchoolRepository 会公开像“GetSchoolsFromCity(Guid cityId)”这样的方法一样。过滤发生在单个聚合而不是两个聚合上的事实没有任何改变。
对此有何看法?
解决方案
在实现查询时,您不必使用域模型,即聚合。您可以查询数据库并根据您需要的数据将您需要的数据提取到一个普通的自定义 dto 中。这样你就可以分离 write model 和 resd model。
推荐阅读
- angular - 菜单下拉菜单
- spring-boot - SPRING MVC:状态=405,错误=不允许方法,消息=不支持请求方法“POST”,ModelAndView
- command-line - Electron 第二个实例的命令行参数已损坏?
- symfony - FormType 中的 Symfony5 自定义验证器 - 选中复选框时验证密码字段
- mongodb - MongoDB - 如何对数组中的日期和计数元素进行分组
- openedge - Progress-4GL:如何在表单中动态添加填写并接受用户输入?
- node.js - MongoError:无条件获取所有数据时池被破坏
- vue.js - Vue devtools 更新但组件没有
- python - 如何只允许 Tkinter 打开而不是命令提示符?
- javascript - Redux saga 在获得连续请求时取消先前