32

我有很多相当有效的代码已经存在了几个月,今天我看到记录了以下异常:

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

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

这个例外到底是什么意思?我应该在我的代码中寻找什么缺陷?

4

2 回答 2

25

如果连接已经有一个未提交的事务并且你再次调用 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是前进的方向。

于 2013-10-25T15:33:10.917 回答
11

对事务使用“错误”方法时也会出现同样的问题,这发生在我们升级到更新版本的实体框架之后。

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

// 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
}

他们在某处使用较新版本的实体框架更改了该事务方法行为的行为,解决方案是使用:

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

请注意,现在调用事务Database而不是Connection.

于 2014-06-03T12:40:38.530 回答