例如,当发生死锁时,将成功执行以下SQL命令,即使它们已分配了回滚后的SQL事务。看起来,这是由在Server上创建的新隐式事务引起的。
有人可以预期,ADO.NET会抛出一个异常,即在僵尸事务上执行命令。但是,不会引发此类异常。(我认为这是ASP.NET中的一个bug。)此外,由于僵尸事务,最终的Dispose()默认忽略回滚。
如果有任何想法,我如何确保没有人能够在隐式事务上执行命令?或者,如何检查交易是僵尸?我发现Commit()和Rollback()检查僵尸事务,但是我可以调用它们进行测试:)
我还发现,也阅读IsolationLevel将进行检查,但我不确定未来的优化器是否会删除简单的调用transaction.IsolationLevel.ToString();。或者您知道有其他安全的方法来调用getter (不使用反射或IL发射)吗?
编辑: Remus Rusanu指出,这种情况通常不会发生。是的,那是真的。它通常发生在代码中有错误时。在我们的例子中,在一个finally语句中有一些日志记录例程,试图将故障存储到数据库中。现在,我正试图找到一个解决方案,如何在未来发现这样的错误。因为这些bug很难测试。如果ADO.NET检查所提供的事务是否是僵尸,这个bug将更容易找到。我发现了两种可能性:
发布于 2010-06-07 16:07:10
你所描述的并不存在。事务回滚将在应用程序中抛出一个非常明显的异常。出于某种原因,我更相信您的代码捕获了异常,并悄悄地忽略了它,在事务回滚后继续执行语句。
发布于 2010-06-20 17:34:59
可能与您的问题没有直接关系,因为它是由bug引起的,但可能仍然值得关注。并不是所有的错误都会导致事务回滚,因此有时事务可能“部分成功”--有些语句错误,而另一些语句则很好。
有一个选项中止使服务器在发生任何错误时中止事务。
考虑到您的问题,您不能关闭隐式事务(如果执行SQL语句,则将创建一个隐式事务,除非另一个事务已处于活动状态)。因此,您只需正确地处理错误,以确保在您需要事务时事务就在那里。
查看一下TransactionScope类,您可以使用它来避免在代码中管理这些事务。
发布于 2010-06-21 19:18:53
//根据您的描述,我猜您的代码有效地做到了这一点
SqlConnection conn = new SqlConnection("ConnectionString");
SqlCommand cmd = new SqlCommand("insert into ....");
cmd.Connection = conn;
conn.Open();
SqlTransaction tran = conn.BeginTransaction();
cmd.Transaction = tran;
tran.Rollback(); //or tran.Dispose();
cmd.ExecuteNonQuery();这将导致在事务范围之外执行cmd。
删除行cmd.Connection = conn;将实现我认为您正在寻找的行为(例如,由于事务不再有效,该命令将失败)。
SqlConnection conn = new SqlConnection("ConnectionString");
SqlCommand cmd = new SqlCommand("insert into ....");
//cmd.Connection = conn;
conn.Open();
SqlTransaction tran = conn.BeginTransaction();
cmd.Connection = tran.Connection;
cmd.Transaction = tran;
tran.Rollback(); //or tran.Dispose();
cmd.ExecuteNonQuery();https://stackoverflow.com/questions/2990387
复制相似问题