【问题标题】:transaction rollback error (This SqlTransaction has completed; it is no longer usable)事务回滚错误(此 SqlTransaction 已完成;它不再可用)
【发布时间】:2014-11-17 15:17:14
【问题描述】:

我正在尝试测试第一个事务,如果它是成功的,那么我尝试第二个事务,如果第二个事务也是一个成功,那么我将两个都提交,如果第二个事务失败,我需要回滚首先。

所以我有以下函数,它返回一个可以是状态之一的字典:

0(表示事务失败但设法回滚)-> sql 事务

1(表示事务成功)-> sql事务

-1(表示事务失败并且没有设法回滚)-> sql 事务

Public Function execDBTrans_valMod(transactionName As String, ByVal emailSubject As String, ByVal emailBody As String, ByVal queryString As String, Optional ByVal connectionString As String = "SQLConnectionHere") As Dictionary(Of Integer, SqlTransaction)
        Dim trans_dict As New Dictionary(Of Integer, SqlTransaction)

        Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings(connectionString).ToString) 'LATEST EXEC
            connection.Open()

            Dim command As New SqlCommand(queryString, connection)
            Dim transaction As SqlTransaction = connection.BeginTransaction(transactionName)
            command.Transaction = transaction

            Try
                command.CommandTimeout = 3600 'Used for large updates
                command.ExecuteNonQuery()
                'transaction.Commit() DO NOT COMMIT so that we can commit only after we verify that pbSite can be inserted

                trans_dict.Add(1, transaction)
                Return trans_dict
            Catch dbTrans_ex As Exception
                Try
                    transaction.Rollback()

                    trans_dict.Add(0, transaction)
                    Return trans_dict
                Catch dbTrans2_ex As Exception

                    trans_dict.Add(-1, transaction)
                    Return trans_dict
                    ' This catch block will handle any errors that may have occurred on the server that would cause the rollback to fail, such as a closed connection.
                End Try
            End Try

        End Using
    End Function

然后我在函数中有以下代码:

Dim transPB_dict = execDBTrans_valMod("transPB", failSubject, failBody, buildInsert)
If transPB_dict.ContainsKey(1) Then 'SUCCESS

    Dim transPBsite_dict = execDBTrans_valMod("transPBsite", failSubject, failBody, buildInsert_PBsite)

    If transPBsite_dict.ContainsKey(1) Then
        transPB_dict.Item(1).Commit()
        transPBsite_dict.Item(1).Commit()
        Return True
    Else 'Failed to create the tables for this user so rollback all the tables that were created in the previous transaction (all the old tables in panelbase)
        transPB_dict.Item(1).Rollback() 'THIS THROWS THE ERROR This SqlTransaction has completed; it is no longer usable

        Return False
    End If

Else
        Return False
End if

我还没有提交第一个事务,为什么我尝试回滚时却说sqlTransaction已经完成...?

感谢您的帮助!

【问题讨论】:

    标签: vb.net commit rollback sqlconnection sqltransaction


    【解决方案1】:

    当你退出 USING 块时

    Using connection As New SqlConnection...
    End Using
    

    您的连接已关闭并被释放,并且针对该连接的任何待处理事务都已提交。您不能针对多个连接进行相同的事务。

    只需创建和打开一次连接。将此连接(和事务)传递给将要处理 SQL 的方法。然后,当一切都完成后,您可以提交您的事务并关闭/释放您的连接。

    处理跨多个 SQL 命令的单个连接将提高程序的速度,因为每个连接都会产生开销,从而减慢您的速度。

    【讨论】:

    • 啊,是的,这当然有道理,谢谢!我已将连接传回并手动关闭它,而不是使用“Using”语句。
    【解决方案2】:

    因为您的连接在execDBTrans_valMod 中打开和关闭。
    当连接关闭时,与该连接关联的事务结束。

    如果您需要在第二个命令失败时回滚第一个命令,您只需要一个事务。
    连接和事务应该由命令执行器的调用者管理。

    你需要这样的东西:

    Public Sub execDBTrans_valMod(ByVal transaction As SqlTransaction, ByVal emailSubject As String, ByVal emailBody As String, ByVal queryString As String)
        Using command As New SqlCommand(queryString, transaction.Connection, transaction)
            Try
                command.CommandTimeout = 3600 'Used for large updates
                command.ExecuteNonQuery()
            Catch ex As Exception
                ' Do something with emailSubject and emailBody??
                ' Then rethrow ex to be caught by the caller.
                Throw
            End Try
        End Using
    End Sub
    

    和调用者:

    Using connection As New SqlConnection(ConfigurationManager.ConnectionStrings("SQLConnectionHere").ToString)
        connection.Open()
        Using transaction As SqlTransaction = connection.BeginTransaction()
            Try
                execDBTrans_valMod(transaction, failSubject, failBody, buildInsert)
                execDBTrans_valMod(transaction, failSubject, failBody, buildInsert_PBsite)
                transaction.Commit()
                Return True
            Catch ex As Exception
                Try
                    transaction.Rollback()
                Catch exRollback As Exception
                    ' Do logging or something when rollback failed.
                End Try
                Return False
            End Try
        End Using
    End Using
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多