检查连接是否处于事务中

问题描述 投票:0回答:4

我收到一个

SqlConnection does not support parallel transactions.
异常,并且 这个答案 在连接尝试打开两个事务时提到了它。这正是我正在做的事情。我认为嵌套事务没问题(我使用 sqlite 作为原型)。

如何检查连接是否已在事务中?我正在使用 Microsoft SQL Server 数据库文件。

sql sql-server
4个回答
8
投票

经过一番搜索,我发现了另一个Stack Overflow问题。 事实证明,您无法在 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
,因为嵌套事务已完全中止。


2
投票

您是从多个线程执行此操作吗?如果是这样,那么询问将无济于事,因为在您询问的时间和开始新事务的时间之间,其他一些线程可能已经开始了自己的事务。您将需要使用连接池来避免这种竞争条件。


0
投票

您可以通过检查

cmd.Transaction
是否为
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;
}

然后父函数可以传入一个命令,并可选择开始它自己的事务块,否则,将由被调用的函数创建并提交一个事务块。


0
投票

检查

Transaction.Current
对象是否为
null
- 请参阅访问当前事务Transaction.Current 属性

© www.soinside.com 2019 - 2024. All rights reserved.