TableAdapterでの手動トランザクションについて

解決


モモ  2006-11-11 00:16:16  No: 134070

VB.NET2005+SQLserver2000です。
TableAdapterでの手動トランザクションについて
下記のようなコードで実現しようとしていますが、TableAdapter.Update時に
「ExecuteNonQuery は、コマンドに割り当てられた接続が保留状態であるローカルのトランザクションにあるとき、トランザクション オブジェクトを持つコマンドが必要です。コマンドの Transaction プロパティがまだ初期化されていません。」
というエラーになります。
--------------------------------------------------------------------
<クラスの定義>
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Reflection

Public Class MyTableAdapter

    Public Shared Function BeginTransaction(ByVal tableAdapter As Object) As SqlTransaction
        Return BeginTransaction(tableAdapter, IsolationLevel.ReadUncommitted)
    End Function

    Public Shared Function BeginTransaction(ByVal tableAdapter As Object, ByVal isolationLevel As IsolationLevel) As SqlTransaction
        ' get the table adapter's type
        Dim type As Type = tableAdapter.GetType()

        ' get the connection on the adapter
        Dim connection As SqlConnection = GetConnection(tableAdapter)

        ' make sure connection is open to start the transaction
        If connection.State = ConnectionState.Closed Then
            connection.Open()
        End If

        ' start a transaction on the connection
        Dim transaction As SqlTransaction = connection.BeginTransaction(isolationLevel)

        ' set the transaction on the table adapter
        SetTransaction(tableAdapter, transaction)

        Return transaction
    End Function

    ''' <summary>
    ''' Gets the connection from the specified table adapter.
    ''' </summary>
    Private Shared Function GetConnection(ByVal tableAdapter As Object) As SqlConnection
        Dim type As Type = tableAdapter.GetType()
        Dim connectionProperty As PropertyInfo = type.GetProperty("Connection", BindingFlags.NonPublic Or BindingFlags.Instance)
        Dim connection As SqlConnection = CType(connectionProperty.GetValue(tableAdapter, Nothing), SqlConnection)
        Return connection
    End Function

    ''' <summary>
    ''' Sets the connection on the specified table adapter.
    ''' </summary>
    Private Shared Sub SetConnection(ByVal tableAdapter As Object, ByVal connection As SqlConnection)
        Dim type As Type = tableAdapter.GetType()
        Dim connectionProperty As PropertyInfo = type.GetProperty("Connection", BindingFlags.NonPublic Or BindingFlags.Instance)
        connectionProperty.SetValue(tableAdapter, connection, Nothing)
    End Sub

    ''' <summary>
    ''' Enlists the table adapter in a transaction.
    ''' </summary>
    Public Shared Sub SetTransaction(ByVal tableAdapter As Object, ByVal transaction As SqlTransaction)
        ' get the table adapter's type
        Dim type As Type = tableAdapter.GetType()

        ' set the transaction on each command in the adapter
        Dim commandsProperty As PropertyInfo = type.GetProperty("CommandCollection", BindingFlags.NonPublic Or BindingFlags.Instance)
        Dim commands() As SqlCommand = CType(commandsProperty.GetValue(tableAdapter, Nothing), SqlCommand())
        Dim command As SqlCommand
        For Each command In commands
            command.Transaction = transaction
        Next

        ' set the connection on the table adapter
        SetConnection(tableAdapter, transaction.Connection)
    End Sub

End Class
--------------------------------------------------------------------
<使用時>
Using Cnn As New SqlClient.SqlConnection(My.Settings.Project1ConnectionString)
  Dim Cmd As SqlClient.SqlCommand = Cnn.CreateCommand()
  Cnn.Open()
  Cmd.Transaction = Cnn.BeginTransaction
  Call MyTableAdapter.SetTransaction(TableAdapter1, Cmd.Transaction)
  Call MyTableAdapter.SetTransaction(TableAdapter2, Cmd.Transaction)
  〜  データセット編集処理  省略  〜
  TableAdapter1.Update(DataSet1.Table1) ←  ここで上記エラー
  〜  データセット編集処理  省略  〜
  TableAdapter2.Update(DataSet1.Table2)
  Cmd.Transaction.Commit()
End Using
--------------------------------------------------------------------
どこを改善すればよろしいでしょうか。
教えて下さい。
よろしくお願い致します。


特攻隊長まるるう  2006-11-14 05:18:39  No: 134071

とりあえずエラーメッセージでぐぐると幾つかの情報が得られました。

省略している部分も含めて、実行するコマンドを削って、どこまでは実行できて、
何を実行するとエラーになるか調べてください。


モモ  2006-12-07 02:31:56  No: 134072

お返事ありがとうございました。
データセットの状態そのままではやはりうまく行きませんでした。
データセットを直接TableAdapter.UPDATEとするのではなく、
追加、変更、削除を行った結果のデータセットから
DataRow.RowStateの状態を見ながら、必要なSQL文(Addedなら
Insert文、DeletedならDelete文等)を生成し、
最終的に生成したSQL分をまとめてトランザクションとして
実行(command.ExecuteNonQueryを使用する通常の方法)するように
しました。
という訳で納得が行きませんが、解決とします。
お騒がせ致しました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加