Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 在一个事务中创建多个聚合_Entity Framework_Architecture_Transactions_Domain Driven Design_Ddd Repositories - Fatal编程技术网

Entity framework 在一个事务中创建多个聚合

Entity framework 在一个事务中创建多个聚合,entity-framework,architecture,transactions,domain-driven-design,ddd-repositories,Entity Framework,Architecture,Transactions,Domain Driven Design,Ddd Repositories,我的有界上下文(库存)接收数量为5的事件。其中5是从仓库卡车上卸下的托盘数量。现在在我的库存BC中,我想创建5个聚合(foreach托盘1聚合)。我如何在我的应用层中做到这一点?如果我只成功创建了其中的3个呢?我不能临时创建它们,因为我的持久存储是基于文件的。我该怎么办?通常的答案是这样的——我们要做的第一件事是将事件保存在“待办事项”列表中 我们对该列表的“订阅”需要跟踪,也就是说写下它在待办事项列表中的位置。例如,我们可以将TODO列表视为仅附加的事件序列,并且订阅会写下最后一个完全处理的事

我的有界上下文(库存)接收数量为5的事件。其中5是从仓库卡车上卸下的托盘数量。现在在我的库存BC中,我想创建5个聚合(foreach托盘1聚合)。我如何在我的应用层中做到这一点?如果我只成功创建了其中的3个呢?我不能临时创建它们,因为我的持久存储是基于文件的。我该怎么办?

通常的答案是这样的——我们要做的第一件事是将事件保存在“待办事项”列表中

我们对该列表的“订阅”需要跟踪,也就是说写下它在待办事项列表中的位置。例如,我们可以将TODO列表视为仅附加的事件序列,并且订阅会写下最后一个完全处理的事件的索引

当订阅运行时,它会在列表中查找第一个未处理的事件,并根据您需要的事务数进行处理。完成所有这些工作后,它会更新自己的计数器(另一个事务),并可以继续

如果处理失败,那么我们永远不会达到“写下来”的步骤;因此,当我们重新启动时,它将尝试再次处理同一事件

为此,我们需要两个属性:一个是再次运行处理器应该为聚合生成相同的标识符列表,并且处理器知道聚合可能已经创建,并在这种情况下采取适当的行动

因此,在最坏的情况下:我们得到了5托盘事件。我们创建了所有5个新聚合,然后在它能够记录事件已被完全处理之前崩溃。流程将重新启动,并开始处理同一事件。它发现每个新聚合都已创建,因此每个步骤都成为禁止操作。最后,在完成事件的所有处理后,它记录事件已完成


换句话说,我们需要幂等处理。

您可能应该将收据事件的记录和五个托盘的生成视为两个独立的事务

在您的案例中,这些更改跨越两个聚合,但是您的应用程序服务最好尽可能多地处理一个聚合域事件是解决此类扩展事务问题的正确结构,无论是单个BC中的聚合之间还是跨BC

因此,您的应用程序服务会将收到的五个托盘记录为一个事务,并生成一个具有足够上下文和数据的域事件(例如
PalletsUnloaded
)。该事件将作为数据结构传递给MessageBroker,由为域事件注册的订阅者检索

然后,托盘聚合将通过特定于事件的订阅者捕获事件,并通过以下两种方式之一对其进行处理:

  • 您可以在一次过程中创建五个托盘。就事务而言,这种方法有点冒险,因为如果您将文件用作持久存储,则可能会出现故障,并且您可能没有细粒度数据来确定确切的问题
  • 捕获事件并创建五条单独的事件消息(比如
    CreatePallet
    ),每条消息都提交回MessageBroker。此事件的订阅者将拾取它们并逐个创建托盘记录。您将准确地知道哪一个失败以及失败的原因
  • 第二种方法也更安全,因为如果使用可靠的消息代理(如RabbitMQ)作为事件的传输机制,则可以将出错的事件发送到死信队列,或设置稍后重试处理的机制。您还可以构建一个单独的错误处理过程/视图来处理和处理错误事件。

    这是一个非常广泛的问题。这很难回答,因为你没有给出任何有意义的,甚至是矛盾的环境细节。标记实体框架和使用基于文件的数据库不会进行计算。我认为您不会使用为EF单元测试而设计的基于文件的数据库。