如何从服务层将分两步执行的两个数据库操作包装在一个事务中?

How to wrap two database actions performed in two steps in a transaction from the service layer?

我有一项服务,我们称它为 MyService.cs,它存在于我的应用程序的业务层中。我的应用程序有 3 层,业务层、持久层和 API(常规干净架构)。 MyService 中的方法需要分两步与存储库进行交互。所以首先它从客户端获取一些输入,将其发送到存储库并将其保存到 Table 1。然后它获取新更新的数据,执行一些逻辑,然后将该数据发送到存储库以进行保存在 Table 2. 现在我想自动执行此操作。也就是说,如果任一数据库保存失败,则进行回滚。但是我无权从服务层访问数据库上下文,所以我无法在那里创建事务。我如何确保这两个过程在没有访问事务的情况下要么失败要么成功?请参见下图中的流程。

我相信您会想要 Unit Of Work pattern 这样的东西。这个想法是在对两个存储库进行更改之前您不会保存,因此它们是作为一个事务的一部分进行的。

don't have access to the db context from the service layer so I can't create a transaction there.

好吧,你确实应该。服务层应该负责指定数据形状(查询)和编排事务。查询和数据形状由服务层的需求驱动,您不应该通过修改存储库层来实现对服务层的更改。做到这一点的唯一方法是让您的存储库层忽略服务的特定要求。同样,不同的数据库读取和写入何时以及是否是单个事务的一部分并不是您的存储库可以或应该知道的。

只需将 DbContext 注入服务层即可编排事务。在同一 DI 范围内执行的其他层将解析 same DbContext 实例。如果您认为它更干净,您可以将 DbContext 包装在自定义的 UnitOfWork 包装器中。

另一种选择是使用 TransactionScope in your Service Layer and rely on that to flow an ambient transaction through to your other layers. You may need to specify the TransactionScopeAsyncFlowOption 进行交易流。