混合使用System.Transactions和SqlTransactions

6
今晚我在学习中加强自己的知识,试图克服因为我之前工作的公司而产生的四年不良编程实践。其中我最近发现的一件事是 System.Transactions。经过几个小时的阅读后,我认为我已经足够了解它们的工作原理和为什么要使用它们。然而,我查看的所有示例都显示内联 T-SQL 被调用于事务中。
在进行数据库访问时,我几乎只使用存储过程,并且所有现有的存储过程都包装在其自己的 SqlTransactions 中。你知道的,“Begin Tran”然后回滚或提交。如果一个存储过程调用另一个存储过程,它也会创建一个事务,并且提交会一直向上传递,直到外部事务提交或者回滚。这很好用。
现在我的问题是,如果我想在我的代码中开始使用 System.Transactions - 仅仅为了监视连续的数据库任务,这些任务无法嵌套在单个存储过程中 - 那么它如何与我已经存在于存储过程中的 SqlTransactions 相关?
在我的存储过程中是否会添加一层保护以便在实际提交之前使用 System.Transactions,或者因为我显式地在我的 SqlTransaction 中提交,那么数据是否仍然会在基于代码的事务提交或回滚时持久化?

这个问题的被接受答案是错误的。在 System.Transaction 中使用 Sql 事务会导致意外行为(即,Sql 事务不参与外部 System.Transaction!)这样做会有效地使您的事务无效化。 - Bill Nadeau
感谢您跟进并进行这些更正,比尔。七年过去了,我甚至无法记得是否最终实施了任何需要这个的东西,但标记正确答案是很好的。 :) - WesleyJohnson
2个回答

6
不要将 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。不幸的是,这意味着必须从所有存储过程中删除您的事务代码,但遗憾的是,这是必要的,因为混合模型无法保证数据的完整性。

如果在SqlCommand中使用显式的ADO.Net事务,并将该事务注册到XA事务中(或者这是否可能),那会怎样呢?这会取消XA事务吗? - STLDev

-1

如果你的存储过程内部事务都被提交了,那么它就能正常工作。如果其中一个事务回滚了,那么外部事务中的所有内容都会回滚。纯魔法。 :)


太好了。这正是我所期望的,也似乎是合乎逻辑的答案,我只是不想假设。非常感谢。 - WesleyJohnson
这绝对是错误的。请参见:https://msdn.microsoft.com/zh-cn/library/ms973865.aspx - Bill Nadeau
已更改接受的答案。 :) - WesleyJohnson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接