今天晚上,我一直在温习我的知识,因为我所在的公司,我试图克服4年来糟糕的编程实践。我最近偶然发现的一件事是System.Transactions。在读了几个小时后,我想我对它们是如何工作的以及为什么你想要使用它们有了足够的理解。然而,我看过的所有示例都显示了从事务内部调用内联T-SQL。
在进行数据库访问时,我主要使用存储过程,现有的存储过程都包装在它们自己的SqlTransactions中。你知道,使用'Begin Tran‘然后回滚或提交。如果一个已存储的Proc调用另一个已存储的proc,它也会创建一个事务,并且提交气泡一直向上,直到外部的proc提交或回滚。效果很好。
所以现在我的问题是,如果我想开始在我的代码中使用System.Transactions -出于监视不能嵌套在单个存储过程中的连续数据库任务的简单目的-如何使用我的存储过程中已有的现有SqlTransactions?
在我的代码中使用System.Transactions只是在实际提交之前增加了一层保护,还是因为我在我的SqlTransaction中显式地提交了数据-无论在基于代码的事务中提交还是回滚,数据都会持久化吗?
发布于 2016-10-19 22:22:42
否,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。不幸的是,这将意味着从所有存储过程中删除事务代码,但遗憾的是,这是必要的,因为使用混合模型无法保证数据的完整性。
发布于 2009-10-25 16:39:34
如果你的内部事务在存储的proc中被提交,那么一切都会被提交。如果它们中的一个回滚,那么外部事务中的所有内容都将回滚。纯粹的魔法。:)
https://stackoverflow.com/questions/1620351
复制相似问题