【问题标题】:Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMITEXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 的数量不匹配
【发布时间】:2016-06-21 22:19:07
【问题描述】:

当以下过程中发生任何错误时,错误消息是“EXECUTE 后的事务计数表示 BEGIN 和 COMMIT 语句的数量不匹配。以前的 count = 1, current count = 0。EXECUTE 之后的事务计数表示 BEGIN 和 COMMIT 语句的数量不匹配。以前的count = 1, current count = 0"

CREATE PROCEDURE [dbo].[proc_PurchaseOrder_Create](@CustomerID INT, @CustomerOrderID INT OUTPUT)          
AS          
SET NOCOUNT ON;          
--------------------------------          
DECLARE @Return_Message VARCHAR(1024)          
DECLARE @ErrorCode  INT            
DECLARE @ErrorStep  VARCHAR(200)          
DECLARE @UserID INT  
--------------------------------          
DECLARE @CustomerCartID INT,@PONumber VARCHAR(255), @CartTotalAmount NUMERIC          

BEGIN TRY          

    BEGIN TRAN                  
  -----------------------------------------------------------------------------             
  SELECT @ErrorCode = @@ERROR          
      SET NOCOUNT ON;      
  IF NOT EXISTS(SELECT CustomerCartID FROM TxnCustomerCart WHERE CustomerID = @CustomerID)           
     BEGIN          
        SET @Return_Message= 'No Cart item is available'          
           SET @ErrorCode = 1          
        END                  
        ELSE          
        BEGIN          
    -----------------------------------------------------------------------------          
    SELECT @UserID = ISNULL(UserID,0) FROM TxnCustomers WHERE CustomerID = @CustomerID      
    -----------------------------------------------------------------------------          
    SELECT @CartTotalAmount = CartTotalAmount, @CustomerCartID = CustomerCartID FROM TxnCustomerCart WHERE @CustomerID = CustomerID            
    SELECT @ErrorStep = 'Error on inserting data into TxnCustomerOrders';            
    INSERT INTO TxnCustomerOrders(CustomerID,OrderDate,OrderStatus,Ramarks,PaymentCategoryCode,CreatedBy,CreatedDatetime)          
    VALUES(@CustomerID,GETDATE(),'PRTRCVD','','Wallet',@UserID,GETDATE())            
    SET @CustomerOrderID = SCOPE_IDENTITY();          

    SELECT @ErrorStep = 'Error on generating PONumber';            
    SET @PONumber =dbo.fun_getPONumber(@CustomerID, @CustomerOrderID)          

    SELECT @ErrorStep = 'Error on inserting data into TxnPurchaseOrder';          

    INSERT INTO TxnPurchaseOrder (CustomerOrderID, PONumber, PODate, POAmount, PODocID, PODocPath, CreatedBy, CreatedDate)          
     VALUES (@CustomerOrderID, @PONumber, GETDATE(), @CartTotalAmount, REPLACE(@PONumber, '/' , '-'), REPLACE(@PONumber, '/' , '-') + '.pdf', @UserID, GETDATE())              

    SELECT  @ErrorCode  = 0, @Return_Message = 'Purchase order successfully created'          
  END       

  SET NOCOUNT OFF;         
    COMMIT TRAN               
    RETURN @ErrorCode -- =0 if success,  <>0 if failure          
END TRY           
BEGIN CATCH          
    IF @@TRANCOUNT > 0 ROLLBACK          

    SELECT @ErrorCode = ERROR_NUMBER()          
        , @Return_Message = @ErrorStep + ' '          
        + cast(ERROR_NUMBER() as varchar(20)) + ' line: '          
     + cast(ERROR_LINE() as varchar(20)) + ' '           
        + ERROR_MESSAGE() + ' > '           
        + ERROR_PROCEDURE()          

    RETURN @ErrorCode -- =0 if success,  <>0 if failure          

END CATCH  

【问题讨论】:

  • 你的 sp 被另一个事务包围了

标签: sql-server transactions entity-framework-6


【解决方案1】:

您还需要考虑 XACT_STATE() 函数的结果。检查MSDN上的块Uncommittable Transactions and XACT_STATE


稍后编辑


我改变了对可能的解决方案的想法 :) 最后我把你的情况复制了。看。 我采用了您的程序,删除了除与异常处理和try\catch 逻辑相关的代码之外的所有代码,并添加了将导致对象名称解析错误(致命错误)的表达式。这是我得到的

CREATE PROCEDURE [dbo].[proc_PurchaseOrder_Create]         
AS          
SET NOCOUNT ON;          
BEGIN TRY          

    BEGIN TRAN   

    print 'before'
    select * from ##global_tmp_table; --> fatal error here
    print 'after'

    COMMIT TRAN         
END TRY           
BEGIN CATCH
    print 'catch'
    IF @@TRANCOUNT > 0 ROLLBACK          
END CATCH  

好的,现在如果我尝试执行此过程,我会得到以下输出

之前 消息 208,级别 16,状态 0,过程 proc_PurchaseOrder_Create,第 29 行 无效的对象名称“##global_tmp_table”。 消息 266,级别 16,状态 2,过程 proc_PurchaseOrder_Create,第 29 行 EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 0,当前计数 = 1。

那么,发生了什么? - 我们的交易保持打开状态 - 您可以通过在同一窗口中执行 print @@TRANCOUNT 来检查这一点

为什么会这样? - 因为 catch 块无法捕获致命错误 - 来自我之前提到的同一个 MSDN article

当以下类型的错误发生在与 TRY...CATCH 构造相同的执行级别时,它们不会由 CATCH 块处理: 编译错误,例如语法错误,阻止批处理运行。 语句级重新编译过程中出现的错误,例如由于延迟名称解析而在编译后出现的对象名称解析错误。

在我们修复这种情况之前,您需要在您尝试执行存储过程的窗口中调用ROLLBACK,以便最终关闭我们的事务。

我们如何解决这个问题? - 我们只需要set XACT_ABORT ON - 你可以在Using TRY…CATCH with XACT_STATE块中的所有同一篇文章中找到一个示例

所以,最后,我们的测试过程应该是这样的

ALTER PROCEDURE [dbo].[proc_PurchaseOrder_Create]         
AS          
SET NOCOUNT ON;  
SET XACT_ABORT ON; --> the only change
BEGIN TRY          

    BEGIN TRAN   

    print 'before'
    select * from ##global_tmp_table;
    print 'after'

    COMMIT TRAN         
END TRY           
BEGIN CATCH
    print 'catch'
    IF @@TRANCOUNT > 0 ROLLBACK          
END CATCH 

现在,在发生致命错误的情况下,数据库引擎将自动回滚事务,您只会得到预期的错误消息

之前 消息 208,级别 16,状态 0,过程 proc_PurchaseOrder_Create,第 31 行 无效的对象名称“##global_tmp_table”。

【讨论】:

  • 这里有几件事,第一件事是我是否需要保持“IF @@TRANCOUNT > 0 ROLLBACK”不变,第二件事是为什么/何时发生此问题。
  • 嗨,@andrey 我得到了你的解决方案,它的工作方式与你在 sql server 中解释的完全一样。但问题是,当我使用实体框架 6 代码从我的 C#.net 调用此过程并将错误记录到错误日志之后的文件中时
  • 错误 [09 Mar 11:04:24][OLMPServices.Controllers.OrderManagementController.OrderPlacement(D:\VSS\Order Lifecycle Management Portal\400_S6_ImplementationAndUnitaryTest_Phase\Source Code\OLMP\Working\OLMP.root\ OLMP\OLMPServices\Controllers\OrderManagementController.cs:242)]- System.Data.SqlClient.SqlException (0x80131904):EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 1,当前计数 = 0。EXECUTE 之后的事务计数表示 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 1,当前计数 = 0。
  • 将数据插入 TxnOrderAddressDetails 8152 行时出错:49 字符串或二进制数据将被截断。 > proc_PurchaseOrder_Create at OLMPBusiness.OrderManagementBusinessComponent.CreatePurchaseOrder(String authToken) in D:\VSS\Order Lifecycle Management Portal\400_S6_ImplementationAndUnitaryTest_Phase\Source Code\OLMP\Working\OLMP.root\OLMP\OLMPBusiness\OrderManagementBusinessComponent.cs:line 198 at
  • OLMPServices.Controllers.OrderManagementController.OrderPlacement() 在 D:\VSS\Order Lifecycle Management Portal\400_S6_ImplementationAndUnitaryTest_Phase\Source Code\OLMP\Working\OLMP.root\OLMP\OLMPServices\Controllers\OrderManagementController.cs :line 232 ClientConnectionId:9bf7d1ec-ea49-49b6-a8e0-bc53d486d99d 错误号:266,State:2,Class:16
猜你喜欢
  • 1970-01-01
  • 2015-06-23
  • 2012-02-18
  • 2018-03-11
  • 2015-12-21
  • 2021-05-23
  • 2014-03-22
  • 2014-10-25
  • 2016-07-21
相关资源
最近更新 更多