无法回滚子交易。未找到该名称的任何事务或保存点

时间:2013-10-08 23:02:47

标签: sql tsql loops transactions

我在sql中有一个循环,它做了一些事情

    begin tran one

    do some inserts in others tables

      --start loop
     begin tran two
      --do something
      begin try
--if something fail then a trigger does rollback and this return a error (and this goes to catch), then don't i need do the rollbak in catch? this could not be dissable because this is working on production
      --something finished ok 
      commit tran two
      end try
      begin catch
     rollback tran two
      end catch

    --finished loop
    commit


----------

我收到了这个错误

  

批次结束时检测到不可提交的交易。该   交易被回滚。

begin tran one
begin tran two

rollback tran two

执行此代码我得到了这个:

  

无法回滚两个。找不到该名称的交易或保存点。

我只希望子查询回滚第二个循环并继续其他记录。

2 个答案:

答案 0 :(得分:10)

操作员回滚回滚所有事务,对于仅回滚第二个循环,您必须使用保存点:

  begin tran one

-- do some inserts in others tables

  --start loop
  save tran two -- begin tran two

  --do something
  begin try
     update product set id = 1 --if something fail then a trigger does rollback and this return a error (and this goes to catch), then don't i need do the rollbak in catch? this could not be dissable because this is working on production

  --something finished ok 
  commit tran two
  end try
  begin catch

    rollback tran two
  end catch

--finished loop
commit

触发示例:

create table product (id int)
GO  
create trigger product_trigger on product for update
as
  set xact_abort off

  if (select count(*) from inserted i join product p on i.id=p.id)=0 begin 
    if (@@trancount>0) begin 
      /* rollback */ 
      raiserror('product does not exist', 16, 1) 
    end 
  end

答案 1 :(得分:2)

就我而言,是我的代码正在通过 EF DbContext 方法(一种包含非嵌套事务的SQL Server存储过程)进行调用。

自从@NotMe已经指出“ there is no such as a nested transaction in SQL Server”以来,我开始怀疑我的过程是否真的不需要事务处理。

怀疑我的DbContext感到内,,我开始检查DbContext选项,直到 DbContext.Configuration.EnsureTransactionsForFunctionsAndCommands = True 引起了我的注意。

因此,一旦我将其值更改为 True ,一切就可以成功运行。

MyDbContext.Configuration.EnsureTransactionsForFunctionsAndCommands = false;

发生了什么事?

在我看来,EF的 ObjectContext.ExecuteFunction 方法正在管理自己的外部事务,作为存储过程内部事务的包装,因此,当我的存储过程的ROLLBACK TRAN被击中时,按下EF的COMMIT / ROLLBACK代码时,没有挂起的事务。

奇怪的是,在收集关于 EnsureTransactionsForFunctionsAndCommands 属性的一些引用时,我发现此默认行为是由于(我认为)EF团队做出的最糟糕的决定之一,因为它与每个团队都会直接冲突。 T-SQL脚本中的ROLLBACK TRAN。

有关更多详细信息,请在EF6 wraps every single stored procedure call in its own transaction. How to prevent this?上查看有洞见的SO的QA

希望它对某人有帮助:-)