我今晚一直在汲取我的知识,试图克服4年糟糕的编程习惯,因为我正在为之工作。我最近偶然发现的一件事是System.Transactions。在阅读了最近几个小时之后,我想我已经充分了解它们的工作原理以及为什么要使用它们。但是,我所看到的所有示例都显示了在事务中调用内联T-SQL。
在进行数据库访问时,我几乎只使用Stored Procedures,现有的存储过程都包含在自己的SqlTransactions中。你知道,使用'Begin Tran'然后回滚或提交。如果Stored Proc调用另一个存储过程,它也会创建一个事务,并且Commits会冒泡,直到外部提交或回滚。效果很好。
所以现在我的问题是,如果我想在我的代码中开始使用System.Transactions - 为了监控不能嵌套在单个存储过程中的连续数据库任务的简单目的 - 它如何与现有的一起工作我的存储过程中已有的SqlTransactions?
在我的代码中使用System.Transactions只是在实际提交之前添加了一层保护,或者因为我在我的SqlTransaction中明确提交 - 无论是在基于代码的事务中提交还是回滚,数据都会被保留?
答案 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)
工作正常,如果存储过程中的内部事务已提交,则所有内容都将提交。如果其中一个回滚,则外部通道内的所有内容都将回滚。纯粹的魔法。 :)