【问题标题】:How handle database Transactions in DDD if Repositories need handle more than one table for get or persist a Domain Model?如果存储库需要处理多个表来获取或持久化域模型,如何在 DDD 中处理数据库事务?
【发布时间】:2021-10-26 12:32:45
【问题描述】:

我正在重构一个项目以使其更接近 DDD。该项目是用 VB.Net 编写的,并使用 WinForms 到 UI。一直在学习DDD,有些东西还不是很清楚。

我使用存储库模式和 SqlKata 来创建和执行 SQL 语句。我阅读了为什么应在应用程序服务中处理事务,但我认为在存储库中处理事务的某些情况可能是个好主意。一个例子:

具有列表属性 Lines 的域模型 Order。名为 FindOrderService 的服务。该服务使用 OrderRepository 及其函数 .FindById(...)。此存储库返回 Order 及其 Lines。在数据库中 OrderOrderLines 是两个不同的表。

I. 存储库函数不应该通过必须使用两个表来确保域对象以一致的状态创建来处理事务吗?使用函数 .Add(...) 不会发生同样的事情吗?

II. 应用程序服务可能会或可能不会以交易方式使用。但他们不知道有多少表用于持久化聚合。即使它也可以从应用程序服务中处理,难道不能确保这样的事情是基础设施的问题吗?

III. 从我读到的。似乎存在两个术语:“业务交易”和“技术交易”(在此post)。这是技术交易的例子吗?

提前致谢!

编辑:

我的问题,更具体地说,是:如果应用程序服务可以选择服务本身是否可以从数据库启动事务,如何从存储库(如果它们使用多个表)确保必须返回或持久化的领域模型是否一致?

我认为在this post 中已经更详细地讨论了这个问题。 This response 与我要找的很接近,但不清楚是否可以使用存储库中的数据库事务或如何正确处理。

【问题讨论】:

    标签: transactions repository domain-driven-design repository-pattern sqlkata


    【解决方案1】:

    我了解了为什么应在应用程序服务中处理事务,但我认为在存储库中处理事务的某些情况可能是个好主意。

    特定场景允许以两种不同的方式完成事情的事实并不意味着我们应该选择“规则破坏者”方式:在事务的上下文中拥有单个存储库并不能证明让存储库拥有事务是合理的.按照设计,事务应跨越一个或多个存储库。

    。事务可以在应用程序级别抽象出来,但“包含”一个查询/更新两个表的存储库以保持一致性。

    。事务、存储库、聚合——所有这些都应该在应用程序级别被抽象出来。确实,基础架构级别是您创建具体实现(技术事务、几个表、一些实体)的地方,但应用程序并不关心单个工作单元(事务)跨越实际上“隐藏”八个表的四个存储库。

    III。商业交易和技术交易可以重叠,但不是必须的。例如,您可以有一个业务流程,其中执行多个技术事务(单个流程可能在不同的数据库上操作),将单个业务事务组合在一起。

    更新:

    确实建议在聚合和事务之间建立 1:1 的关系,但是聚合可以嵌入其他非聚合实体,即本地实体(例如订单及其订单行),一对一-many方式,可以很自然的体现为DB中的两个表(父表,子表)。所以很明显,为了保持域模型的一致性,可以在一个事务的上下文中更新多个表。

    使用能够跟踪一组更改并立即提交/撤消它们的数据存储引擎来识别术语“存储库”是有意义的。但更重要的是,代码上下文中的存储库是与此类存储通信的对象的抽象,并且可以决定设计两个存储库接口:一个用于父表 (IOrder) , 第二个是子表 (IOrderLine)。

    存储库不负责提供有关域模型一致性的保证。存储库只是与数据存储进行通信的接口,应用层负责适当的编排,即将一个或多个存储库接口限定为单个工作单元(例如事务)。应用服务使用领域模型提供的工具定义业务流程,可以是单个存储库接口持久保存两个表,也可以是两个存储库接口每个持久一个表。

    【讨论】:

    • 首先,感谢您的回复。我仍然很难理解这一点并解释我的疑问以及我想要的。请告诉我我是否理解您的回复:我在视频中听到并在文章中读到一个事务只能处理一个聚合,因此一个存储库。这条规则是我不理解您的第二 (II) 回复的原因。 (继续...)
    • [...] 我的问题,更具体地说,是:如果应用程序服务可以选择服务本身是否可以从数据库启动事务,如何从存储库(如果他们使用多个表)必须返回或持久化的域模型是一致的?我的想法是:从存储库检查事务是否尚未开始,然后存储库开始事务。 Application Service 不应该仅仅因为 Repository 需要使用多个表而开始 Transaction,因为它不知道这一点。
    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 2018-06-15
    • 2016-04-22
    • 2015-01-31
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 2021-02-14
    相关资源
    最近更新 更多