.net嵌套事务作用域



我们认为我们理解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),但数据库事务保存点与分布式事务不兼容,这并不奇怪。

最新更新