- - PR -
SqlDataSourceにトランザクションをかけて複数テーブルの更新
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2007-03-15 19:48
こんばんは。
SqlDataSourceにトランザクションをかけて 複数テーブルのインサートや更新をかけたいと思っています。 以下を参考にして実現方法は確認できたのですが ちょっと使い勝手が良くないので 他にも方法があれば、お聞かせ下さい。 (SqlDataSourceのこんな使い方自体、強引なんでしょうか?) ○参照サイト http://kova.la.coocan.jp/blog/2006/03/sqldatasource.html ■環境 OS :Windows Server 2003 R2 SP1 アプリ:Visual Studio 2005 SQL :SQL Server 2005 SP1 ===================================================== ■前提 ・テーブルAとBの2つのテーブルがある。 ・SqlDataSourceのIDは、「SqlDataSource1」 ・テーブルAに対するインサートSQL文は、「sql」 ・テーブルBに対するインサートSQL文は、「sql2」 ===================================================== ■処理の流れ (1)テーブルAをインサート時に発生するイベントで トランザクションをつける。 (2)テーブルAのインサートが終わった時に発生するイベントで テーブルBのインサート処理を行う。 (3)テーブルAとBのインサート結果件数(成功時は各々1になる)から ロールバックorコミットを行う。 ===================================================== ■ソース Dim sql As String = "" Dim sql2 As String = "" 'インサート処理 Protected Sub DbInsert() sql = "INSERT INTO tableA …(省略)" sql2 = "INSERT INTO tableB …(省略)" Try SqlDataSource1.InsertCommand = sql SqlDataSource1.InsertCommandType = SqlDataSourceCommandType.Text intRetCnt = SqlDataSource1.Insert() Catch Finally End Try End Sub '(1) Protected Sub SqlDataSource1_Inserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) Handles SqlDataSource1.Inserting Dim command As DbCommand Dim connection As DbConnection Dim transaction As DbTransaction command = e.Command connection = command.Connection connection.Open() transaction = connection.BeginTransaction() command.Transaction = transaction End Sub '(2) Protected Sub SqlDataSource1_Inserted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs) Handles SqlDataSource1.Inserted Dim command As DbCommand Dim transaction As DbTransaction command = e.Command transaction = command.Transaction Dim intAffectA As Integer = 0 Dim intAffectB As Integer = 0 '------------------------------- 'テーブルAの結果 intAffectA = e.AffectedRows '------------------------------- 'テーブルBの処理 Try command.CommandText = sql2 intAffectB = command.ExecuteNonQuery() Catch Finally End Try '------------------------------- '(3) '2つの更新結果による最終処理 If intAffectA > 0 And intAffectB > 0 Then transaction.Commit() Else transaction.Rollback() End If End Sub | ||||
|
投稿日時: 2007-03-16 12:54
何に関して"使い勝手が良くない"と思っていらっしゃるのかはわかりませんが、
例えばTransactionScopeによる暗黙的なトランザクションを利用すると、以下のように記述できます。(注:未検証)
まぁ、そもそもSqlDataSourceは単純な追加・更新・削除処理にしか向かないと思います。 (僕なら、SqlDataSourceに追加処理をやらせておきながらその後自分でデータアクセスしたりするのはNGです。) | ||||
|
投稿日時: 2007-03-16 14:37
よこけん様 お返事ありがとうございます。
> 何に関して"使い勝手が良くない"と思っていらっしゃるのかはわかりません 言葉足らずで申し訳ありません。 私のテストプログラムでは、テーブルAのインサート実行時のイベントを拾って トランザクションやテーブルBの処理を差し込む形になっています。 理想としては、SqlDataSourceを使わない手法と同じ流れで Sub DbInsert()内だけで (1)DB接続Open (2)トランザクション開始 (3)テーブルAのインサート処理実行(ExecuteNonQuery) ※失敗したらDB接続Close (4)テーブルBのインサート処理実行(ExecuteNonQuery) ※失敗したらロールバックして DB接続Close (5)コミット (6)DB接続Close という処理の流れができれば、ソースが簡潔になるし 1つ目の処理(ここではテーブルAのインサート処理)が インサート時は、Handles SqlDataSource1.Inserting 削除時は、Handles SqlDataSource1.Deleting …etc といった1つ目の処理内容の事も考えなくても 同じロジックを使えるのに…と思ったんです。 (他ページで同じような処理があった時とか) サンプルソースありがとうございます。 Sub DbInsert()内だけで処理が完結していて スッキリしています! 参考にさせて頂きます。 > そもそもSqlDataSourceは単純な追加・更新・削除処理にしか向かないと思います。 やはり、そうですか。 アドバイスありがとうございます。 [ メッセージ編集済み 編集者: sakusaku 編集日時 2007-03-16 14:38 ] |
1