SQL错误“在批处理结束时检测到不可提交的事务”没有db上的事务

时间:2014-05-27 14:14:45

标签: c# sql sql-server transactions

我在代码的不同位置遇到以下问题。 从DB(SQL Server)返回SqlException,并在调用存储过程后显示消息“在批处理结束时检测到不可用事务。事务已回滚”。存储过程结构遵循以下示例:

USE [EXAMPLE_DB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_ExampleStoredProcedure]
@Parameter INT, @AnotherParameter INT

AS
BEGIN
    BEGIN TRY

    SET NOCOUNT ON;


    DECLARE @Variable INT;
    DECLARE @AnotherVariable CHAR;
    DECLARE @ErrMsg VARCHAR;

    SET @ErrMsg = '';

    /*Doing Some Stuff Here (Select, IF-THEN, etc...)

            /* I call another stored procedure */   
            EXECUTE [dbo].[sp_SecondStoredProcedure] 
                       @Param = 'Blabla'
                      ,@Param2 = 'BlaBlaBla'


            /*Here I handle some custom output parameters from second stored                           
                     procedure to handle errors */



                    /* Other stuff here */

END TRY

BEGIN CATCH    
        SET @CustomExitCode = 'XXXXX';
        SET @ErrMsg = (SELECT ERROR_MESSAGE()); 
END CATCH;

END

如您所见,在存储过程内部没有事务处理。 我使用TransactionScope类处理事务代码端(C#),在事务范围内调用各种存储过程,包括上面的那个(失败的那个)。

问题是:为什么SQL谈论Uncommitable Transaction,如果我没有SQL端的事务,但只有try-catch块,而代码上执行了所有事务处理?

我已经在网上搜索过并发现了很多关于“不可提交的事务”错误的资料,但实际上在SQL端都有事务处理。

我希望我以一种可以理解的方式解释了这个问题。 我显然可以获得更多信息。

非常感谢你的帮助!

干杯, 加布里埃尔

2 个答案:

答案 0 :(得分:0)

汇总事务中TRY BLOCK中的所有操作,让sql server为您处理,而不是在应用程序中处理它。在Try Block中明确地BEGIN TRAN和COMMIT Trans,如果在此事务中出现任何问题,请回滚它。

我会做点像......

ALTER PROCEDURE [dbo].[sp_ExampleStoredProcedure]
@Parameter INT, @AnotherParameter INT
AS
BEGIN
    SET NOCOUNT ON;
 BEGIN TRY
    DECLARE @Variable INT;
    DECLARE @AnotherVariable CHAR;
    DECLARE @ErrMsg VARCHAR;

    SET @ErrMsg = '';
BEGIN TRANSACTION;      --<-- Begin here 

    /*Doing Some Stuff Here (Select, IF-THEN, etc...)*/

            /* I call another stored procedure */   
            EXECUTE [dbo].[sp_SecondStoredProcedure] 
                       @Param = 'Blabla'
                      ,@Param2 = 'BlaBlaBla'
            /*Here I handle some custom output parameters from second stored                           
                     procedure to handle errors */

                    /* Other stuff here */
COMMIT TRANSACTION;     --<-- Commit here if nothing gone wrong

END TRY

BEGIN CATCH    
  IF (@@TRANCOUNT > 0)
   BEGIN
      ROLLBACK TRANSACTION;   --<-- Rollback if something went wrong
   END

           /*Other error logging here*/
        SELECT @CustomExitCode = 'XXXXX', @ErrMsg = ERROR_MESSAGE(); 
END CATCH;

END

答案 1 :(得分:0)

如果您在“代码”中开始交易,那么该交易也将对程序可见。否则,怎么会是真正的交易?

当您将事务与 try catch 和错误结合使用时,会发生很多错误(尤其是在使用 XACT_ABORT ON 时)将导致“不可提交的事务错误”,请参阅 XACT_STATE 文档。

发生错误时,您必须对事务做一些事情,如果不这样做,它会在离开程序时自动回滚。

出于这些和其他原因,我们通常避免将 try catch 与事务一起使用。由于您使用的是 C# 代码,您不妨将 try catch 移至应用程序部分,并将事务处理与 XACT_ABORT ON 一起保持,这意味着它将在出错时回滚