我收到SqlConnection does not support parallel transactions.
个异常,this answer在连接尝试打开两个事务时提到它。这正是我在做的事情。我认为嵌套的事务是可以的(我使用sqlite作为原型)。
如何检查连接是否已在交易中?我正在使用Microsoft SQL Server数据库文件。
答案 0 :(得分:5)
经过一番搜索,我发现了另一个Stack Overflow question。事实证明,您无法在ADO.NET中嵌套事务。当您尝试时,您可能最终会启动两个不相关的事务,这会导致并行事务错误。
要查看某个连接当前是否在某个交易中,您可以:
var com = yourConnection.CreateCommand();
com.CommandText = "select @@TRANCOUNT";
var trancount = com.ExecuteScalar();
返回嵌套事务的数量。
请注意,您可以手动嵌套事务,而无需使用SqlTransaction对象。例如:
var com = yourConnection.CreateCommand();
com.CommandText = "BEGIN TRANSACTION";
com.ExecuteNonQuery();
com.CommandText = "BEGIN TRANSACTION";
com.ExecuteNonQuery();
com.CommandText = "INSERT INTO TestTable (name) values ('Joe');";
com.ExecuteNonQuery();
com.CommandText = "COMMIT TRANSACTION";
com.ExecuteNonQuery();
com.CommandText = "ROlLBACK TRANSACTION";
com.ExecuteNonQuery();
com.CommandText = "SELECT COUNT(*) FROM TestTable";
Console.WriteLine("Found {0} rows.", com.ExecuteScalar());
这会打印0
,因为嵌套的事务已完全中止。
答案 1 :(得分:2)
你是从多个线程做的吗?如果是这样,那么请求将无济于事,因为在您询问的时间和开始新事务的时间之间,其他一些线程可能已经开始了自己的事务。您将需要使用连接池来避免这种竞争条件。
答案 2 :(得分:0)
我认为当你的代码不知道时,只有Try / Catch会这样做。什么语言?
答案 3 :(得分:0)
您可以通过检查null
是否为//begin transaction unless one was already started
bool newTransaction = cmd.Transaction == null;
if (newTransaction) cmd.Transaction = cmd.Connection.BeginTransaction();
try {
// do Stuff Here
cmd.ExecuteNonQuery();
cmd.ExecuteNonQuery();
// commit if it's our to commit
if (newTransaction) cmd.Transaction.Commit();
} catch (SqlException ex) {
if (newTransaction && cmd.Transaction != null) cmd.Transaction.Rollback();
throw;
}
来检查交易是否已打开。
然后相应地包装你的代码,这样如果一个事务已经打开,那么调用函数拥有该事务并将其提交/适当地回滚。
{{1}}
然后父函数可以传入一个命令,并可选择开始它自己的事务块,否则,将由被调用的函数创建并提交一个。