“SqlConnection不支持并行事务”是什么时候发生?

35

我有很多代码已经在这里工作了好几个月,今天我看到了以下异常记录:

System.InvalidOperationException
SqlConnection does not support parallel transactions.
    at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(
       IsolationLevel iso, String transactionName)
    at System.Data.SqlClient.SqlConnection.BeginTransaction(
       IsolationLevel iso, String transactionName)
    at my code here

我希望调查一下为什么会抛出这个异常。我已经阅读了 BeginTransaction() 的MSDN描述,它只是说有时会抛出这个异常。

这个异常究竟意味着什么?我的代码存在什么缺陷,我应该寻找什么?


你是在使用常规的SqlConnection/SqlCommand/SqlDataAdapter还是使用ORM(如EF或L2S或其他)?代码是否使用显式事务或TransactionScopes?此外,您能否发布围绕记录/抛出异常的错误的代码示例? - SimonGoldstone
请查看此答案:https://dev59.com/TkbRa4cB1Zd3GeqPxSC6 它是关于同样的问题。 - sergiogarciadev
1
@SimonGoldstone:如果我能够缩小问题范围,我就不会问这个问题了。我不是在问“我的代码无法工作,请尽快帮助”,而是在问我需要在我的代码中寻找什么。 - sharptooth
1
为了缩小问题范围,你是使用常规的SqlConnection/SqlCommand/SqlDataAdapter还是使用ORM(如EF或L2S或其他)?代码是否使用显式事务或TransactionScopes? - SimonGoldstone
@SimonGoldstone:该代码直接使用 SQL???相关内容,没有使用任何中间件,并且使用 SqlTransaction 进行事务管理。 - sharptooth
2个回答

27

如果连接已经有一个未提交的事务并且您再次调用BeginTransaction,则会出现此错误。

在这个例子中:

class Program
{
    static void Main(string[] args)
    {
        using (SqlConnection conn = new SqlConnection("Server=.;Database=TestDb;Trusted_Connection=True;"))
        {
            conn.Open();

            using (var tran = conn.BeginTransaction())
            {
                using (var cmd = new SqlCommand("INSERT INTO TESTTABLE (test) values ('" + DateTime.Now.ToString() + "')", conn))
                {
                    cmd.Transaction = tran;
                    cmd.ExecuteNonQuery();
                }

                using (var tran2 = conn.BeginTransaction())    // <-- EXCEPTION HERE
                {
                    using (var cmd = new SqlCommand("INSERT INTO TESTTABLE (test) values ('INSIDE" + DateTime.Now.ToString() + "')", conn))
                    {
                        cmd.Transaction = tran2;
                        cmd.ExecuteNonQuery();
                    }

                    tran2.Commit();
                }

                tran.Commit();
            }
        }
    }
}

第二次BeginTransaction抛出了完全相同的异常。

在下一个事务之前,请确保第一个事务已提交或回滚。

如果您想要嵌套事务,您可能会发现TransactionScope是向前的方法。


12

当使用“错误”的方法进行事务时,就会出现相同的问题。这在我们升级到新版本的Entity Framework后发生了。

过去,我们使用以下方法创建事务,并混合使用EF强类型linq查询和Sql查询,但自从 Connection 属性不再存在后,我们用 db.Database 替换了所有的 db.,这是错误的:

// previous code
db.Connection.Open();
using (var transaction = db.Connection.BeginTransaction())
{
    // do stuff inside transaction
}
// changed to the following WRONG code
db.Database.Connection.Open();
using (var transaction = db.Database.Connection.BeginTransaction())
{
    // do stuff inside transaction
}

某处使用Entity Framework的新版本更改了该交易方法的行为,解决方法是使用:

db.Database.Connection.Open();
using (var transaction = db.Database.BeginTransaction())
{
    // do stuff inside transaction
}

请注意,该交易现在是在Database上调用,而不是Connection


这个解决方案解决了我的问题,因为我正在使用EF数据库优先模型,并且我使用了一个“非事务连接”来执行事务内其他表的查询。 - David Espino
我发现TransactionScope在EF中也非常好用。我已经很久没有使用BeginTransaction了。几乎所有的事务工作都是在TransactionScopes内完成的。 - SimonGoldstone
4
感谢您发布这个帖子,我遇到了完全相同的问题。虽然它不是针对楼主特定情况的答案,但我还是点了+1。 - Raithlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接