P. *_*een 5 sql-server transactions entity-framework-6
当以下过程中发生任何错误时,错误消息为“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
Run Code Online (Sandbox Code Playgroud)
您还需要考虑 XACT_STATE() 函数的结果。检查MSDN上的不可提交事务和 XACT_STATE块
\n\n稍后编辑
\n\n我改变了对可能的解决方案的想法:)\n最后我重现了您的情况。看。\n我采用了您的过程,删除了除与异常处理和逻辑相关的代码之外的所有代码try\\catch,并添加了将导致对象名称解析错误(致命错误)的表达式。这是我得到的
CREATE PROCEDURE [dbo].[proc_PurchaseOrder_Create] \nAS \nSET NOCOUNT ON; \nBEGIN TRY \n\n BEGIN TRAN \n\n print \'before\'\n select * from ##global_tmp_table; --> fatal error here\n print \'after\'\n\n COMMIT TRAN \nEND TRY \nBEGIN CATCH\n print \'catch\'\n IF @@TRANCOUNT > 0 ROLLBACK \nEND CATCH \nRun Code Online (Sandbox Code Playgroud)\n\n好的,现在如果我尝试执行此过程,我会得到以下输出
\n\n之前\n消息 208,级别 16,状态 0,过程 proc_PurchaseOrder_Create,第 29 行\n无效的对象名称 \'##global_tmp_table\'。\n消息 266,级别 16,状态 2,过程 proc_PurchaseOrder_Create,第 29 行\nEXECUTE 后的事务计数表示BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 0,当前计数 = 1。
\n\n所以发生了什么事?-我们的交易保持开放状态- 您可以通过print @@TRANCOUNT在同一窗口中执行来检查这一点
为什么会发生这种情况?-因为 catch 块无法捕获致命错误- 来自我之前提到的同一篇 MSDN文章
\n\n当以下类型的错误发生在与 TRY\xe2\x80\xa6CATCH 构造相同的执行级别时,CATCH 块不会处理这些错误:\n阻止批处理运行的编译错误,例如语法错误。\n错误在语句级重新编译期间发生的错误,例如由于延迟名称解析而在编译后发生的对象名称解析错误。
\n\n在我们修复这种情况之前,您需要ROLLBACK在尝试执行存储过程的窗口中进行调用,以便最终关闭我们的事务。
我们该如何解决这个问题?- 我们只需要- 您可以在使用 TRY\xe2\x80\xa6CATCH 和 XACT_STATE块的set XACT_ABORT ON所有同一篇文章中找到示例
所以,最后,我们的测试程序应该是这样的
\n\nALTER PROCEDURE [dbo].[proc_PurchaseOrder_Create] \nAS \nSET NOCOUNT ON; \nSET XACT_ABORT ON; --> the only change\nBEGIN TRY \n\n BEGIN TRAN \n\n print \'before\'\n select * from ##global_tmp_table;\n print \'after\'\n\n COMMIT TRAN \nEND TRY \nBEGIN CATCH\n print \'catch\'\n IF @@TRANCOUNT > 0 ROLLBACK \nEND CATCH \nRun Code Online (Sandbox Code Playgroud)\n\n现在,在出现致命错误的情况下,数据库引擎将自动回滚事务,您将只得到预期的错误消息
\n\n之前\n消息 208,级别 16,状态 0,过程 proc_PurchaseOrder_Create,第 31 行\n无效的对象名称 \'##global_tmp_table\'。
\n| 归档时间: |
|
| 查看次数: |
16405 次 |
| 最近记录: |