You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:48:50