在DDD中,每个存储库或有界上下文或事务的UoW?

won*_*rld 5 domain-driven-design unit-of-work repository-pattern

在DDD中,聚合根可以具有存储库.让我们采用Order聚合,它是非持久的对应OrderRepository和持久对应的OrderUoW.我们还有ProductVariant聚合,它跟踪订单中产品的库存.它可以有ProductVariantRepositoryProductVariantUoW.

Order和ProductVariant的工作方式是在订单持久化之前,检查库存.如果有库存,则通过调用OrderUoW.Commit()来保持订单.是的,接下来将调用ProductVariantUoW.Commit()来更新产品的库存.

不幸的事情可能会变坏,用户在短时间内购买相同的产品(将其视为两个用户购买相同产品的网络应用程序).现在,第二个用户的整个事务应该通过还原刚刚创建的订单而失败.我应该调用OrderUoW来回滚更改(应该从数据库中删除顺序)吗?或者我应该将两个UoW.Commit()操作放在事务范围中,因此一个commit()失败会回滚更改吗?或者两个存储库(Order,ProductVariant)应该只有UoW并且它只需要一个事务范围?

我可以通过说明如何处理涉及多个存储库的事务来简化故事?

Eri*_*idt 1

我们可以问的一个问题是谁在做以下事情:

Order 和 ProductVariant 的工作方式是在保留订单之前检查库存。如果有库存,则将通过调用 OrderUoW.Commit()来保留订单。是的,接下来将调用 ProductVariantUoW.Commit() 来更新产品的库存。

有人认为这种工作属于服务层,它允许服务层将跨聚合对象的事物放入单个事务中。

根据http://www.infoq.com/articles/ddd-in-practice

一些开发人员更喜欢在 DAO 类中管理事务,这是一个糟糕的设计。这会导致事务控制过于细粒度,从而无法灵活地管理事务跨越多个域对象的用例。服务类应该处理事务;这样,即使事务跨越多个域对象,服务类也可以管理事务,因为在大多数用例中,服务类处理控制流。

我认为,作为使用单个交易的替代方案,您可以使用 ProductVariant 声明库存,并且,如果所有必需的库存项目均可用,则您可以提交订单。否则(即您无法领取订单所需的所有产品),您必须退回使用补偿交易成功领取的库存。结果是,在订单提交失败的情况下,某些库存将暂时显示为无法用于其他订单,但优点是您可以在没有分布式事务的情况下工作。

尽管如此,这个逻辑仍然属于服务层,而不是 DAO 类。