如何检测到发生回滚?

sta*_*and 8 c# sql-server msdtc

我正在寻找一个大型业务应用程序中的一个错误,该错误中的业务流程失败了,但是部分持久化到了数据库中。为了使问题更难弄清,该过程每隔几周就会失败一次,每次失败之间都会成功处理数十万次。当并发性/工作进程数增加时,错误频率似乎会增加。

到目前为止,我们已经能够重新创建该程序所看到的内容。(.NET 4.7.1框架)

using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    using (var sqlConnection = new SqlConnection("Server=localhost;Database=Database1;Trusted_Connection=True"))
    {
        sqlConnection.Open();

        // Doing some unwanted nested manual transaction and rolling it back
        var transaction = sqlConnection.BeginTransaction();
        new SqlCommand($"INSERT INTO TestTable VALUES('This will be rolled back}')", sqlConnection).ExecuteNonQuery();

        transaction.Rollback();

        // Now doing some work with the DB.
        // You might expect it to become a part of transactionScope, but that is NOT the case!
        // So this command will actually succeed, with data written to the DB.
        new SqlCommand($"INSERT INTO TestTable VALUES('This will be inserted')", sqlConnection).ExecuteNonQuery();

        // Doing something which promotes the local transaction to a distributed transaction.
        using (var sqlConnection2 = new SqlConnection("Server=localhost;Database=Database2;Trusted_Connection=True"))
        {
            // The program will fail here, with message "The transaction has aborted, Failure while attempting to promote transaction."
            sqlConnection2.Open();

            new SqlCommand($"INSERT INTO TestTable2 VALUES('We will never come this far')", sqlConnection2).ExecuteNonQuery();

        }
    }
    transactionScope.Complete();
}
Run Code Online (Sandbox Code Playgroud)

我们的生产代码未明确调用transaction.Rollback(),在我的示例中只是将其作为重现错误消息和行为的方式。但是,如果我们的任何第三方库都发出了此调用,我想抛出异常并尽快退出。最好在应用层。

如何检测到Rollback()已拨打电话?我真的不想做粗野的操作,而不能确保它transactionScope能够做到这一点。

更新1

我不需要的“回滚”是由.Net的连接共享机制中的某个错误引起的。该错误在4.5.1和4.8之间的所有.Net Framework版本以及新的System.Data.SqlClient程序包上均被复制。

一个问题已经被添加到System.Data.SqlClient的存储库

Dav*_*oft 2

不同的事务 API 并不都能一起工作。所以你现在正处于危险的境地。

如何检测是否已调用 Rollback()?

select @@trancount应该总是告诉你。回滚会将 @@trancount 恢复为 0。