.net 事务嵌套存储过程事务的处理方法

网上有很多这样的问题分析,无非以下两种情况:

1、begin tran 后没有rollback tran 或commit tran

2、应用程序数据库连接事务不在一个会话中;


但以后我要说的情况有点特别,先说一下场景:

1、.net 开发环境

2、使用sqlconnection对象发起事务

3、事务内有多个存储过程

4、各存储过程内有自已的事务

总之就是sqlconnection事务嵌套存储过程事务,以下是演示代码,先看看这样做会有什么问题

以下是VB.NET代码,什么语言不重要,只要是用.net 环境和SqlConnection对象就符合条件

'事务嵌套测试
    Sub testtrans()
        Dim mycn As SqlConnection
        Dim tran As SqlTransaction
        Dim inputs As New Dictionary(Of String, Object)
        Dim outputs As New Dictionary(Of String, SqlParameter)
        mycn = obj.GetSqlConnection
        obj.openSqlConnection(mycn)
        Dim errMsg As String
        Dim cmd As SqlCommand
        Try
            tran = mycn.BeginTransaction
            '存储过程输入参数
            inputs.Add("@test", 1)
            '存储过程输出参数
            outputs.Add("@result", New SqlParameter("@result", SqlDbType.VarChar, 10))
            '执行这事出错,提示EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 
            '             语句的数目不匹配。上一计数 = 1,当前计数 = 0。

            obj.execProc("test_pro1", inputs, outputs, errMsg, tran)<span style="white-space:pre">	</span>'自定义的执行存储过程的方法
            If tran.Connection IsNot Nothing Then
                tran.Commit()
            End If
        Catch ex As Exception
            If tran.Connection IsNot Nothing Then
                tran.Rollback()
            End If
            Me.callBack(False, ex.Message)
            Exit Sub
        Finally
            obj.closeSqlConnection(mycn)
        End Try

以下是存储过程

ALTER PROCEDURE [dbo].[test_pro1]
@test INT,
@result VARCHAR(10) OUTPUT
AS
BEGIN TRANSACTION 
  SET @result='A'
 DECLARE @aa INT
 set @aa=5/0
ROLLBACK TRANSACTION 
通过.net事务调用含事务的存储过程,只要存储过程触发rollback tranaction,会马上触发.net事务异常,即

---------------------

EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

---------------------

这样的异常,但实际上存储过程是按要求执行的,返回参数也返回预期值,也正确回滚了;

如何处理这种问题呢?比较简单,只要在catch对错误码准确判断即可,如下代码:

    cmd.ExecuteNonQuery()
        Catch ex As SqlException
            If ex.Number <> 266 Then
                errMsg = "执行" & procName & "出错,错误码:" & errcode
                WriteLog(errMsg & ",详情:" & Chr(13) & ex.Message & Chr(13) & ex.StackTrace)
            End If
266是事务计数器异常代码,是这个代码直接当正常即可,因为存储过程参数返回到上一级方法后,再判断参数值是否正确,若正常就继续,不正常就退出方法,当然最上一级sqlconnection要对事务做一下判断 

Catch ex As Exception
            If _tran IsNot Nothing Then
                If _tran.Connection IsNot Nothing Then
                    _tran.Rollback()
                End If
            End If
            obj.WriteLog("XX,错误代码:" & errnum & Chr(13) & ex.StackTrace)
            Return obj.CallBack(False, "XX,错误代码:" & errnum)
        Finally
            obj.closeSqlConnection(cn)
        End Try
注:sqlconnection的事务对象sqlTransaction,要用引用传值方式给内部执行存储过程的sqlCommand对象的transaction属性;

另外,我认为.net完全没有必要触发异常,.net的事务是要提交还是回滚,.net本来就提供了判断事务是否有效的方法,如果有效且没有其他异常,手动提交,反之回滚;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值