使用SqlTransactions混合System.Transactions

时间:2009-10-25 08:26:07

标签: c# asp.net sql-server ado.net

我今晚一直在汲取我的知识,试图克服4年糟糕的编程习惯,因为我正在为之工作。我最近偶然发现的一件事是System.Transactions。在阅读了最近几个小时之后,我想我已经充分了解它们的工作原理以及为什么要使用它们。但是,我所看到的所有示例都显示了在事务中调用内联T-SQL。

在进行数据库访问时,我几乎只使用Stored Procedures,现有的存储过程都包含在自己的SqlTransactions中。你知道,使用'Begin Tran'然后回滚或提交。如果Stored Proc调用另一个存储过程,它也会创建一个事务,并且Commits会冒泡,直到外部提交或回滚。效果很好。

所以现在我的问题是,如果我想在我的代码中开始使用System.Transactions - 为了监控不能嵌套在单个存储过程中的连续数据库任务的简单目的 - 它如何与现有的一起工作我的存储过程中已有的SqlTransactions?

在我的代码中使用System.Transactions只是在实际提交之前添加了一层保护,或者因为我在我的SqlTransaction中明确提交 - 无论是在基于代码的事务中提交还是回滚,数据都会被保留?

2 个答案:

答案 0 :(得分:5)

不,System.Transactions和Sql事务不会混合。

我引述,"不要混淆他们"来自以下MSDN文章:https://msdn.microsoft.com/en-us/library/ms973865.aspx

Sql事务不以您希望的方式参与外部System.Transaction。失败或回滚的Sql事务不会导致System.Transaction中的其他活动回滚。

此示例显示了这些现象:

using (var tx = new TransactionScope())
{
    using (var con = new SqlConnection($"{connectionstring}"))
    {
        con.Open();

        using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value1', '{Guid.NewGuid()}'); rollback;", con))
        {
            // This transaction failed, but it doesn't rollback the entire system.transaction!
            com.ExecuteNonQuery();
        }

        using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value2', '{Guid.NewGuid()}'); commit;", con))
        {
            // This transaction will actually persist!
            com.ExecuteNonQuery();
        }
    }
    tx.Complete();
}

在空数据存储上运行此示例之后,您应该注意到第二个Sql操作中的记录确实已提交,而C#代码的结构意味着它们不应该是。

简单地说,你不应该混合它们。如果您在应用程序中编排多个Sql事务,则应该只使用System.Transactions。不幸的是,这意味着从您的所有存储过程中删除您的事务代码,但是,有必要像混合模型一样,您无法保证数据的完整性。

答案 1 :(得分:-1)

工作正常,如果存储过程中的内部事务已提交,则所有内容都将提交。如果其中一个回滚,则外部通道内的所有内容都将回滚。纯粹的魔法。 :)

相关问题