我可以在一个事务中更新同一类型的多个聚合实例吗?

时间:2017-02-08 02:35:31

标签: domain-driven-design

很抱歉,如果它重复,我已经搜索了很多,但我没有找到匹配的问题。

我知道我们不应该在一个事务中更新多个聚合实例。但是,我认为"多个聚合实例"这里表示不同聚合类型的多个实例。我是对的吗?

说,产品 BacklogItem 是两种不同的聚合,因此我们应避免在一次交易中同时更新Product和BacklogItem。

但是如果我需要更新相同聚合类型的多个实例呢?说,我需要更新所有产品'名称。处理它的最佳方法是什么?

伪代码

//Application Service
public void ChangeTitle(string newName)
{
    using(uow.BeginTransaction())
    {
         IEnumerable<Product> products = repo.GetAll();
         foreach(var product in products)
         {
             product.ChangeName(newName);
         }
    }
}

3 个答案:

答案 0 :(得分:3)

AR的类型无关紧要,AR始终是事务边界。与许多人合作时,您通常应该接受部分失败和最终的一致性。

如果没有不变量可以保护所有这些AR,为什么所有重命名都会失败或成功。例如,如果UI确实允许用户一次重命名多个产品,而某些用户则重命名数百个产品。如果一个产品由于并发冲突而无法重命名,那么最好不要重命名任何产品或告知用户其中一个产品失败了吗?

您总是可以违反规则,但您必须明白,事务中涉及的AR越多,您就越有可能因并发冲突而遇到事务性故障(假设可能发生争用)。

当有不变量越过ARs边界时,我通常只在一个事务中修改多个AR,并且我可以避免处理最终的一致性。

答案 1 :(得分:0)

指导的原因与并发访问的期望有关。根据您一次访问系统的用户数量,单个事务中更改的内容越多,并发更改的风险就越大,这将是:

  • 如果使用乐观并发管理,则会导致因并发冲突而导致的错误或异常
  • 如果使用悲观并发管理,
  • 会因锁定而导致延迟
  • 如果不使用并发管理,则会导致数据一致性问题

本指南适用于正在变化的事物的大小是否变得更广(更改更多类型的聚合)或更深(更改相同聚合的更多实例)。考虑到,这种变化的某些部分与另一个人同时做出的类似变化相冲突的风险是什么,而不是考虑到究竟发生了什么变化呢?

为高度并发的多用户系统设计DDD是设计小型独立聚合的指导来源。如果情况不是这样,那么您可能会根据自己的风险分析违反指南。

答案 2 :(得分:0)

聚合用于保护事务边界。从我在伪代码中看到的内容,您将在一个事务中更改它们。

有没有理由在一次交易中完成?如果是这样,那么你的模型中似乎缺少一个概念。这个概念可能只是一个简单的流程管理器,可以更新域中的多个聚合,并在一切成功完成后报告,甚至可以包含一些重试机制或其他异常处理,以防其中一个更新失败。此流程管理器可以命名为“批量重命名”&#39;或类似的东西?

我会以这样的方式对这样的批量重命名模型进行建模,使其将自身注册为需要更新的聚合中的所有域事件的使用者,然后更新这些聚合的名称(可能并行)然后继续监听对于域事件。收到所有事件后,它可以报告它已完成重命名所有聚合,并执行异常处理。