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

非TransactionScope事务隔离级别指定及类型转换报错解惑

问题解析与修复方案

这个问题我之前帮不少开发者排查过,核心是命名空间的枚举混淆,再加上代码里有两个关键的遗漏点,咱们一步步来解决:

一、先解决隔离级别类型转换错误

你遇到的无法将‘System.Transactions.IsolationLevel’转换为‘System.Data.IsolationLevel’错误,本质是枚举的命名空间冲突:

  • SqlConnection.BeginTransaction()方法要求传入的是System.Data命名空间下的IsolationLevel枚举;
  • 如果你的代码顶部同时引用了using System.Transactions;和using System.Data;,编译器会搞不清你用的是哪个枚举,就会抛出这个转换错误。

修复方式二选一:

  • 方式1:明确指定命名空间
    把事务开启的代码改成:
    transaction = connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);
    
  • 方式2:优化命名空间引用
    去掉不需要的using System.Transactions;(如果你没用到TransactionScope的话),或者给枚举取别名:
    using DataIsolation = System.Data.IsolationLevel;
    // 然后开启事务时用:
    transaction = connection.BeginTransaction(DataIsolation.RepeatableRead);
    

二、你的代码存在两个关键遗漏点

1. SqlCommand未关联到事务

你创建了SqlTransaction对象,但没有把它绑定到SqlCommand的Transaction属性上!这会导致你的INSERT操作根本不在事务范围内执行——哪怕后面执行Rollback(),这条INSERT已经被提交到数据库了,完全失去了事务的原子性。

必须加上这行代码:

cmd.Transaction = transaction;

2. 缺失异常处理逻辑

如果在ExecuteScalar()或者CreateSalesLinesWithForLoop()过程中抛出异常(比如数据库连接中断、约束冲突),你的代码会直接跳出using块,根本不会执行Rollback(),这会导致事务处于悬挂状态,占用数据库资源。

需要用try-catch块包裹事务操作,确保异常时能回滚。

修正后的完整代码

public bool CreateSale(Sale sale) {
    int count = 0;
    bool isSuccessful = false;
    using (SqlConnection connection = DBConnection.OpenConnection()) {
        connection.Open(); // 注意:如果OpenConnection()没打开连接,这里要手动Open
        SqlTransaction transaction = null;
        using (SqlCommand cmd = connection.CreateCommand()) {
            try {
                // 明确指定System.Data下的隔离级别
                transaction = connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);
                // 把命令关联到事务
                cmd.Transaction = transaction;

                cmd.CommandText = $"INSERT INTO Sale(total_price, customer_id) OUTPUT INSERTED.id VALUES (@p1, @p2);";
                cmd.Parameters.AddWithValue("@p1", sale.TotalPrice);
                cmd.Parameters.AddWithValue("@p2", sale.Customer.Id);
                sale.Id = (int)cmd.ExecuteScalar();
                
                count = _salesLineDB.CreateSalesLinesWithForLoop(sale, connection);
                
                if (count == sale.SalesLines.Count) {
                    transaction.Commit();
                    isSuccessful = true;
                } else {
                    transaction.Rollback();
                }
            } catch (Exception ex) {
                // 异常时务必回滚事务
                transaction?.Rollback();
                // 可以在这里记录日志或者重新抛出异常
                throw;
            }
        }
    }
    return isSuccessful;
}

另外补充一点:如果你的DBConnection.OpenConnection()方法返回的是未打开的连接,记得要手动调用connection.Open(),否则BeginTransaction()会抛出异常。

内容的提问来源于stack exchange,提问作者user9476827

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:08:39