我正在尝试向我们的数据库对象添加事务支持。 该对象是Remoting对象。 (这是为了确保在Windows客户端上不需要数据库连接。)
现在我想添加对交易的支持; 基本上,客户需要像这样使用它;
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:由于该对象并行使用,似乎也会引发此“内部致命错误”。也许那是不可能的?
答案 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
我没有测试过这个,但它应该让你知道我的意思。只需确保在每种可能的情况下关闭并处理您的连接和交易。