.net嵌套事务作用域
本文关键字:作用域 嵌套事务 net | 更新日期: 2023-09-27 18:28:28
我们认为我们理解transactionscope和嵌套(transactionscope.requests)-即
-------------------------------------------------------内部|外部|-------------------------------------------------------提交|回滚|未提交任何更改commit|commit|所有更改都已提交回滚|回滚|未提交任何更改回滚|commit|----不起作用----
然而,我想知道,是否有任何方法可以创建事务范围、嵌套事务范围、依赖事务、自定义事务或其他类似的事务,其中回滚提交场景也适用?-
即,无论出于何种原因,库函数中都有自己的事务,该事务位于父事务下。如果内部事务成功,那么外部事务可以访问任何更改,但是如果内部事务回滚,则外部事务仍然处于完全可用的状态,并且完全不受内部事务的影响,就好像它从未被调用过一样?
没有,我相信你想错了。这一切仍然只是一个单独的事务,只是嵌套允许感兴趣的代码块投票决定事务是否成功(而不必传递事务对象),而不是说你正在创建嵌套的事务。这就是transactionscope上的方法被称为Complete而不是Commit的原因。
编辑以处理OP 的评论
为了得到您想要的东西,我认为您必须创建两个TS对象,第二个对象带有RequiresNew,然后根据需要分别完成/回滚。我不知道第一个事务是否会从第二个事务发生变化,你必须自己进行实验,看看TS是否能在这里有所帮助。
我理解你想做什么,我并不是说你尝试是错误的;如果这是您的用例所需要的,那么这就是它所需要的。
然而,我不认为TS是为这个用例设计的,我认为引用嵌套事务的文档是不幸的,因为它并不像通常讨论的那样真正嵌套事务(例如在TSQL中)。
TS是为更常见的用例而设计的,其中组件A&B都做事务性工作,A使用B作为其工作的一部分,但B也可以独立使用。TS允许B始终是事务性的,无论是独立使用还是作为A工作的一部分,并且启动事务或重用A(因为A是UoW),而不必绕过事务对象。
不作为事务范围。
如果您的事务都是针对数据库资源管理器(这是托管TransactionScope的绝大多数使用),那么您可以利用数据库功能。数据库支持事务保存点。实际实现因数据库而异,让我们谈谈SQL Server。
您可以直接在T-SQL中利用事务保存点,例如,请参阅异常处理和嵌套事务:
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
end catch
end
go
此过程模板允许在出现异常时进行优雅的恢复,允许在外部工作继续并提交的同时回滚内部工作。
您可以在托管代码中执行与使用SqlTransaction.Save()
和SqlTransaction.Rollback Method (String)
相同的操作。
但是,这些都不受System.Transactions API的支持。考虑到System.Transactions的主要角色之一是管理分布式事务(多个RM),但数据库事务保存点与分布式事务不兼容,这并不奇怪。