SqlConnection事务支持

时间:2012-01-04 09:35:28

标签: vb.net transactions remoting

我正在尝试向我们的数据库对象添加事务支持。 该对象是Remoting对象。 (这是为了确保在Windows客户端上不需要数据库连接。)

现在我想添加对交易的支持; 基本上,客户需要像这样使用它;

  1. BeginTransaction
  2. 的ExecuteNonQuery( “插入...”)
  3. 的ExecuteNonQuery( “插入...”)
  4. 提交/回滚
  5. 
    Public Function ExecuteNonQuery(ByVal Query As String) As Integer
       Dim intResult As Integer = -1
    Using conn As New SqlConnection(Me.strConnectionString)
    Using cmd As New SqlCommand(Query, conn)
    conn.Open() intResult = cmd.ExecuteNonQuery()
    End Using End Using Return intResult End Function

    所以我遇到的问题是,当我在上面的方法中使用新连接(using conn...)时,我无法真正创建事务。

    所以我认为我需要在方法之外移动SqlConnection实例并将其更改为类级变量。但这不是我认为最好的做法。 (?)除此之外:按顺序执行大量查询会导致错误:“内部致命错误”。

    有没有人可以指出我正确的方向?我在网上找到的所有示例都通过直接按顺序执行多个查询以最简单的方式覆盖事务。

    编辑:有点像this question(如何在.NET中为多个SqlConnections使用单个SqlTransaction?)。所以也许这是不可能的,但有没有解决办法?

    编辑2:由于该对象并行使用,似乎也会引发此“内部致命错误”。也许那是不可能的?

2 个答案:

答案 0 :(得分:1)

我认为您可以将SqlConnection对象作为类的字段。

Class SQLHelp
    Implements IDisposable
    Private ReadOnly _conn As SqlConnection
    Private _trans As SqlTransaction

    Public ReadOnly Property Connection As SqlConnection
        Get
            Return _conn
        End Get
    End Property

    Sub New(strConnectionString)
        _conn = New SqlConnection(strConnectionString)
        _trans = Nothing
    End Sub

    Public Function ExecuteNonQuery(ByVal Query As String) As Integer
        Dim intResult As Integer = -1

        If _trans Is Nothing Then
            Using cmd As New SqlCommand(Query, _conn)

                If _conn.State <> ConnectionState.Open Then
                    _conn.Open()
                End If
                intResult = cmd.ExecuteNonQuery()

            End Using
        Else
            Using cmd As New SqlCommand(Query, _conn, _trans)

                If _conn.State <> ConnectionState.Open Then
                    _conn.Open()
                End If
                intResult = cmd.ExecuteNonQuery()

            End Using
        End If
        Return intResult
    End Function

    Public Function BeginTransaction() As SqlTransaction
        _trans = _conn.BeginTransaction()
        Return _trans
    End Function

    Public Sub SubmitTransaction()
        If Not (_trans Is Nothing) Then
            _trans.Commit()
        End If
        _trans = Nothing
    End Sub

    Public Sub RollbackTransaction()
        If Not (_trans Is Nothing) Then
            _trans.Rollback()
        End If
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose

        If Not (_trans Is Nothing) Then
            _trans.Dispose()
        End If

        _conn.Close()
        _conn.Dispose()

    End Sub
End Class

当您使用此课程时,您可以尝试以下代码。

    Using _sqlHelp As New SQLHelp(connectionString)
       _sqlHelp.BeginTransaction()
       'ExecuteNonQueryCode
       _sqlHelp.Commit() 'Or _sqlHelp.Rollback()
    End Using

你怎么看?

答案 1 :(得分:1)

我认为你需要建立连接类级别。我要做的是检查是否已经有连接,然后如果没有创建那个和交易,如果需要。跟踪它直到调用commit或rollback。我不认为在这种情况下使用类级私有字段有任何问题。

这样的事情:

Public Class SqlHandler
    Implements IDisposable

    Private mConnection As SqlConnection
    Private mTransaction As SqlTransaction
    Private strConnectionString As String

    Public Sub New()

    End Sub

    Public Sub New(UseTransaction As Boolean)
        mConnection = New SqlConnection
        If UseTransaction Then
            mTransaction = mConnection.BeginTransaction()
        End If
    End Sub

    Public Function ExecuteNonQuery(ByVal Query As String) As Integer
        Dim intResult As Integer = -1

        Using mConnection As SqlConnection
            Using cmd As New SqlCommand(Query, mConnection, mTransaction)
                cmd.Transaction = mTransaction
                mConnection.Open()
                intResult = cmd.ExecuteNonQuery()
            End Using
        End Using
        Return intResult
    End Function

    Public Sub Commit()
      If mTransaction IsNot Nothing Then
        mTransaction.Commit()
        mTransaction.Dispose()
      End If
          mConnection.Close()
          mConnection.Dispose()
    End Sub

#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls

    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                If mTransaction IsNot Nothing Then
                    mTransaction.Rollback()
                    mTransaction.Dispose()
                End If
                If mConnection IsNot Nothing Then
                    mConnection.Close()
                    mConnection.Dispose()
                End If
            End If
        End If
        Me.disposedValue = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class

我没有测试过这个,但它应该让你知道我的意思。只需确保在每种可能的情况下关闭并处理您的连接和交易。