EXECUTE之后的事务计数表示BEGIN和COMMIT的数量不匹配

时间:2016-03-08 05:07:49

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

当在以下proc中发生任何错误时,错误消息为“EXECUTE之后的事务计数表示BEGIN和COMMIT语句的数量不匹配.Previous if (convertView==null){ convertView = mInflater.inflate(R.layout.list_row, null); holder = new ViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.user_name); holder.sports = (TextView) convertView.findViewById(R.id.user_sports); holder.location = (TextView) convertView.findViewById(R.id.user_location); holder.number = (TextView) convertView.findViewById(R.id.user_contact); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } holder.name.setText(rowItem.getName()); holder.sports.setText(rowItem.getSports()); holder.location.setText(rowItem.getLocation()); holder.number.setText(rowItem.getNumber()); return convertView; 。EXECUTE之后的事务计数表示BEGIN和COMMIT语句的数量不匹配。上一个count = 1, current count = 0

count = 1, current count = 0

1 个答案:

答案 0 :(得分:2)

您还需要考虑XACT_STATE()函数的结果。检查MSDN

上的不可提交的交易和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

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

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

我们如何解决这个问题? - 我们只需要set XACT_ABORT ON - 您可以在使用TRY ... CATCH和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'。