.Net Core跨DLL事务异常:lib.ParamsInsert操作无法随主事务回滚
解决.NET Core跨DLL事务回滚不一致的问题
这个问题我之前也碰到过,核心原因很明确:你在lib.ParamsInsert里单独开启并提交了独立事务,当这个方法里的transaction.Commit()执行完成后,Params的插入操作已经永久写入数据库了。后续主事务触发回滚时,只能撤销主事务范围内的操作(比如Acenta的添加),但已经提交的独立事务是没法被回滚的。
下面给你几个可行的解决方案,按推荐程度排序:
方案一:由主逻辑统一控制事务,Lib方法仅做数据操作
这是最简洁的方式,让Lib层的方法只负责数据操作,不管理事务边界,事务完全由调用方(主逻辑)控制。
修改Lib层的ParamsInsert方法
去掉内部的事务管理和SaveChanges调用,只负责添加实体:
public Params ParamsInsert(DbContext db, Params obj) { // 仅添加实体到上下文,不保存也不处理事务 return db.Params.Add(obj).Entity; }
修改主事务代码
由主逻辑统一处理事务和保存操作:
spcarikart.Repository lib = new spcarikart.Repository(); using (var transaction = db.Database.BeginTransaction()) { try { var result = db.Acenta.Add(obj).Entity; var a = lib.ParamsInsert(db, new Params { Baslik = "Bahdir", Deger = "1" }); // ....其他业务操作 // 统一保存所有上下文变更 db.SaveChanges(); // 提交主事务,所有操作才会真正生效 transaction.Commit(); return result; } catch (Exception ex) { transaction.Rollback(); // 这里可以添加异常日志等处理 } }
方案二:传递主事务对象给Lib方法
如果Lib方法需要自己调用SaveChanges(比如有独立的业务校验逻辑),可以把主事务对象传递给Lib方法,让Lib的操作加入到主事务中。
修改Lib层的ParamsInsert方法
接收主事务对象,不再创建独立事务:
public Params ParamsInsert(DbContext db, Params obj, IDbContextTransaction mainTransaction) { var resul = db.Params.Add(obj).Entity; // 可以正常调用SaveChanges,但变更会被纳入主事务 db.SaveChanges(); return resul; }
修改主事务代码
将主事务对象传入Lib方法,统一提交:
spcarikart.Repository lib = new spcarikart.Repository(); using (var transaction = db.Database.BeginTransaction()) { try { var result = db.Acenta.Add(obj).Entity; var a = lib.ParamsInsert(db, new Params { Baslik = "Bahdir", Deger = "1" }, transaction); // ....其他业务操作 db.SaveChanges(); transaction.Commit(); return result; } catch (Exception ex) { transaction.Rollback(); } }
方案三:使用TransactionScope实现自动事务管理
如果你的场景涉及多个DbContext或者更复杂的跨组件事务,可以用TransactionScope来自动管理事务边界,它会自动将同一范围内的所有数据库操作纳入同一个事务。
注意事项
需要先安装System.Transactions NuGet包(.NET Core/.NET 5+需要手动安装),异步场景要加上TransactionScopeAsyncFlowOption.Enabled。
修改主事务代码
spcarikart.Repository lib = new spcarikart.Repository(); // 开启事务范围,异步场景必须指定AsyncFlowOption using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) { try { var result = db.Acenta.Add(obj).Entity; var a = lib.ParamsInsert(db, new Params { Baslik = "Bahdir", Deger = "1" }); // ....其他业务操作 db.SaveChanges(); // 标记事务完成,所有操作才会提交 scope.Complete(); return result; } catch (Exception ex) { // 不需要手动回滚,TransactionScope会自动处理 } }
修改Lib层的ParamsInsert方法
去掉内部的事务管理,直接操作数据:
public Params ParamsInsert(DbContext db, Params obj) { var resul = db.Params.Add(obj).Entity; db.SaveChanges(); return resul; }
内容的提问来源于stack exchange,提问作者Bahadır Demir
相关产品推荐
相关产品推荐

