ASP.NET Core + EF Core 跨服务依赖操作的数据库事务管理方案求助
ASP.NET Core + EF Core 跨服务依赖操作的数据库事务管理方案求助
最近在做一个ASP.NET Core Web API项目,用EF Core当ORM,每个实体都用了仓储模式来封装数据库访问——主要是因为项目要连的数据库只能在公司内网访问,用仓储的话方便我不在公司时Mock数据层继续开发。常规的CRUD都是按 控制器→服务→仓储 的流程走,只有仓储类直接持有DbContext,服务本身碰不到DbContext。
现在碰到个麻烦事:有些关联的操作需要保证事务性,比如我有两个实体A和B,A依赖B。对应的服务分别是AService(依赖IBService和IARepository)、BService(依赖IBRepository),仓储则是ARepository和BRepository,都持有DbContext实例。
当通过AService创建A对象时,流程大概是这样的:
public async Task<ADto> CreateA(CreateARequest req) { BDto createdB; try { // 先创建A依赖的父级B对象 createdB = await bService.CreateB(req.CreateBReq); } catch (Exception) { // 异常处理逻辑 ... } /* 到这里BService已经通过BRepository创建了B对象,而且每个CRUD操作都会调用SaveChanges() */ ADto createdA; try { A entityObj = CreateEntityFromReq(req); createdA = await repo.Create(entityObj); } catch (Exception) { /* 这里我得手动删除已经创建的B对象来回滚,但我想把整个流程做成一个事务,就不用这么麻烦了。 可问题是服务层拿不到DbContext,没法干净地协调事务 */ ... } ... }
现在的痛点是:如果创建A失败,我得手动删除已经创建的B来保证数据一致性,这不仅繁琐还容易出错。我想把“创建B→创建A”这两步做成一个原子事务,但服务层没有DbContext的访问权限,没法直接管理事务。
目前我想了两个思路:
- 写一个
TransactionManager(DbContext db)类,让服务依赖这个管理器,专门用来启动、提交、回滚事务。 - 给仓储的CRUD方法加个
commitTransaction的布尔参数,同时在服务里加一套不带自动提交的CRUD方法(比如CreateBNoCommit),这样AService可以先调用bService的无提交创建B方法,最后等A也创建完了再统一提交。但感觉这个方案会让代码变复杂,而且容易遗漏提交或者重复提交。
但我不确定这两个方案哪个更靠谱,或者有没有更优雅的、符合分层架构的解决办法?想请教下大家的建议。
内容来源于stack exchange
相关产品推荐
相关产品推荐

