DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ADO.NET トランザクションについて

環境/言語:[VB.NET]
分類:[.NET]

お世話になります。

SQL SERVERのテーブルを更新しようとしています。
しかし、トランザクション処理を書き込むとエラーが出てしまいます。
どの部分がおかしいか、または、コードの不足など不具合があれば、
指摘して頂けませんでしょうか。
更新処理には、Dim command As SqlClient.SqlCommandを定義し、
sql文をcommand.ExecuteNonQuery()で実行しています。
エラーメッセージは、
command.ExecuteNonQuery()は、コマンドに割り当てられた接続に保留状態であるローカルのトランザクションにあるとき、トランザクションオブジェクトが持つコマンドが必要です。コマンドのTransaction プロパティがまだ初期化されていません。
と出ている状態です。
また、エラーではなく警告として、
変数 'trn' は、値が割り当てられる前に使用されています。Null 参照の例外が実行時に発生する可能性があります。
と出て、trn.Rollback()が指摘されています...


Private Sub Button_Update_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Update.Click

    Dim trn As SqlClient.SqlTransaction 'トランザクション

    Try
        'トランザクション開始
        trn = cn.BeginTransaction

        '更新処理

        'コミット
        trn.Commit()

    Catch ex As Exception
        'エラーメッセージを表示
        MessageBox.Show(ex.Message & vbCrLf & ex.StackTrace)

        'ロールバック
        trn.Rollback()

    End Try

End Sub
■No28571に返信(むちかさんの記事)
> SQL SERVERのテーブルを更新しようとしています。
> しかし、トランザクション処理を書き込むとエラーが出てしまいます。
> (snip)
> 更新処理には、Dim command As SqlClient.SqlCommandを定義し、
> sql文をcommand.ExecuteNonQuery()で実行しています。
> エラーメッセージは、
> command.ExecuteNonQuery()は、コマンドに割り当てられた接続に保留状態であるローカルのトランザクションにあるとき、トランザクションオブジェクトが持つコマンドが必要です。コマンドのTransaction プロパティがまだ初期化されていません。
> と出ている状態です。

例外の詳細どおりだと思いますが違うのでしょうか。
そうだと仮定すると、検索エンジンによりすぐ答えは見つかりそうです。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=32511&forum=7

> また、エラーではなく警告として、
> 変数 'trn' は、値が割り当てられる前に使用されています。Null 参照の例外が実行時に発生する可能性があります。
> と出て、trn.Rollback()が指摘されています...

それは、

 Dim trn As SqlClient.SqlTransaction = Nothing

と書いていないからですね。
ありがとうございます。
以下のように変更することでうまくいきました。
command.Transaction = trn が抜けていたようです。

command.ExecuteNonQueryを調べいる途中に新しい疑問がでてきたのですが、
command.ExecuteNonQueryはInteger型で返り値を持つようです。
正常な更新がされたときは1を返すので、更新処理のところで、
Dim count As Integer

count = Update_Record(sql文)
if count <> 1 then
    MessageBox.Show("ERROR.")
    Exit Sub
End If

とした方がいいのでしょうか。
特になくとも動くので、どういう意図があるのかよくつかめていません・・・

Private trn as SqlClient.SqlTransaction 'トランザクション

Private Sub Button_Update_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Update.Click

    Try
        'トランザクション開始
        trn = cn.BeginTransaction

        '更新処理
        Update_Record(sql文)

        'コミット
        trn.Commit()

    Catch ex As Exception
        'エラーメッセージを表示
        MessageBox.Show(ex.Message & vbCrLf & ex.StackTrace)

        'ロールバック
        trn.Rollback()

    End Try

End Sub

    Private Function Update_Record(ByVal sql As String) As Integer

        Dim command As SqlClient.SqlCommand
        command = cn.CreateCommand
        command.Transaction = trn

        command.CommandText = sql

        'コマンド実行
        Return command.ExecuteNonQuery

    End Function
■No28575に返信(むちかさんの記事)
> command.ExecuteNonQueryを調べいる途中に新しい疑問がでてきたのですが、
> command.ExecuteNonQueryはInteger型で返り値を持つようです。
> 正常な更新がされたときは1を返すので、更新処理のところで、
> Dim count As Integer
>
> count = Update_Record(sql文)
> if count <> 1 then
> MessageBox.Show("ERROR.")
> Exit Sub
> End If
>
> とした方がいいのでしょうか。
> 特になくとも動くので、どういう意図があるのかよくつかめていません・・・

そういう基本的なところはリファレンスで調べることができます。
http://msdn.microsoft.com/ja-jp/library/system.data.sqlclient.sqlcommand.executenonquery.aspx

MSDN ライブラリのとおりで、戻り値は影響を受けた行の数です。

特に知る必要がなければ、戻り値は必要ありません。
失敗した時は例外が発生しますので、成功可否に使う必要はありません。
なるほど・・
一応質問の前に調べてはいるのですが、まだ習い始めて数日なものでなかなか上場を取捨選択できない状態です。
やはり成功可否に使う必要はないのですね。

今回も、どうもありがとうございました。
解決済みにチェックを入れ忘れていました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板