- - PR -
複数テーブルのUPATE
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2009-03-04 13:17
言語:Microsoft Visual Studio 2008
データベース:SQL Server 2005 いつもお世話になります。複数のテーブルの更新処理を行いたいのですが、下記のように 記述すると支店テーブルしか更新されません。 テーブルは銀行テーブル(T_GINKO)と支店テーブル(T_SHITEN)があります。 <テーブル構造> 銀行テーブル 支店テーブル GIN_CD GIN_MEI GST_GIN_CD GST_CD GST_MEI 0001 あああ銀行 0001 001 ○○支店 0002 いいい銀行 0001 002 △△支店 複数のテーブルを更新する場合どうすればいいのでしょうか? ご教授お願いします。 Private Function Data_Update() As String Dim sqlConn As SqlConnection = Nothing Dim sqlTrans As SqlTransaction = Nothing Dim strsql As String Dim I As Integer Try Dim sqlDA1 As SqlDataAdapter = New SqlDataAdapter() Dim sqlDA2 As SqlDataAdapter = New SqlDataAdapter() Dim ds1 As DataSet = New DataSet() Dim ds2 As DataSet = New DataSet() Dim sqlCmdBldr1 As SqlCommandBuilder = New SqlCommandBuilder(sqlDA1) Dim sqlCmdBldr2 As SqlCommandBuilder = New SqlCommandBuilder(sqlDA2) sqlDA1.SelectCommand = New SqlCommand() sqlDA2.SelectCommand = New SqlCommand() '<--- 銀行テーブル更新 ---> strsql = "SELECT * FROM T_GINKO" sqlDA1.SelectCommand.CommandType = CommandType.Text sqlDA1.SelectCommand.CommandText = strsql sqlDA1.SelectCommand.Connection = New SqlConnection(My.Settings.MyAppConnect) sqlConn = sqlDA1.SelectCommand.Connection sqlConn.Open() sqlTrans = sqlConn.BeginTransaction(IsolationLevel.Serializable) sqlDA1.SelectCommand.Transaction = sqlTrans sqlDA1.Fill(ds1, "GINKO") Dim newRow As DataRow newRow = ds1.Tables("GINKO").NewRow newRow.Item("GIN_CD") = "0001" newRow.Item("GIN_MEI") = "あいう銀行" ds1.Tables("GINKO").Rows.Add(newRow) sqlCmdBldr1.GetUpdateCommand.Connection = sqlConn sqlCmdBldr1.GetUpdateCommand.Transaction = sqlTrans '<--- 支店テーブル更新 ---> strsql = "SELECT * FROM T_SHITEN" sqlDA2.SelectCommand.CommandType = CommandType.Text sqlDA2.SelectCommand.CommandText = strsql sqlDA2.SelectCommand.Connection = New SqlConnection(My.Settings.MyAppConnect) sqlConn = sqlDA2.SelectCommand.Connection sqlConn.Open() sqlTrans = sqlConn.BeginTransaction(IsolationLevel.Serializable) sqlDA2.SelectCommand.Transaction = sqlTrans sqlDA2.Fill(ds2, "SHITEN") Dim newRow As DataRow newRow = ds2.Tables("SHITEN").NewRow newRow.Item("GST_GIN_CD") = "0001" newRow.Item("GST_CD") = "001" newRow.Item("GST_MEI") = "○○支店" sqlCmdBldr2.GetUpdateCommand.Connection = sqlConn sqlCmdBldr2.GetUpdateCommand.Transaction = sqlTrans ' --- DataSet に対する更新結果をDB へ反映 --- sqlDA1.Update(ds1, "GINKO") sqlDA2.Update(ds2, "SHITEN") ds1.Dispose() ds2.Dispose() sqlTrans.Commit() Catch ex As IndexOutOfRangeException sqlTrans.Rollback() MessageBox.Show("既に削除された可能性があります", AppName, MessageBoxButtons.OK) Catch ex As Exception sqlTrans.Rollback() AppErrorHandler(ex) Finally If Not sqlTrans.Connection Is Nothing Then sqlTrans.Rollback() End If If Not (sqlConn.State = ConnectionState.Closed) Then sqlConn.Close() End If End Try End Function | ||||
|
投稿日時: 2009-03-04 15:52
ざっとしか見てませんが、
銀行テーブルのupdateしてcommitする前にsqlTransに 別のコネクションの別のトランザクションをセットしてるからじゃないですか? | ||||
|
投稿日時: 2009-03-04 16:17
銀行テーブル1件に付き、支店テーブル1件は必ず存在するため、 支店テーブルでエラーが起きた場合、銀行テーブルの更新も支店テーブルの 更新もロールバックしたいと思っています。 この場合どうすればいいのでしょうか? | ||||
|
投稿日時: 2009-03-04 19:20
うまくいかないのは、変数を使いまわしている部分があるためです。
片方だけ追加される状況を避けたいのだと思いますが 今回のケースではコネクションもトランザクションも1つにしたほうがわかりやすいかもしれません。 | ||||
|
投稿日時: 2009-03-04 19:39
すみません。
>今回のケースではコネクションもトランザクションも1つにしたほうがわかりやすい>かもしれません。 の意味をもう少し教えて下さい。 | ||||
|
投稿日時: 2009-03-04 20:18
こんばんは、かずいです。
この中でコネクションとトランザクションが2回発行されているので、これを sqlconn = new sqlconnection(My.Settings.MyAppConnect) sqlconn.open sqltrans = sqlConn.BeginTransaction(IsolationLevel.Serializable) sqlDA1.SelectCommand.Connection = sqlconn sqlDA1.SelectCommand.Transaction = sqlTrans sqlDA2.SelectCommand.Connection = sqlconn sqlDA2.SelectCommand.Transaction = sqlTrans 見たいな感じにすればいいという感じだと思います。 コネクションとトランザクション、コミットの関係をきちんと整理して おいた方が良いと思いますよ。 基本的にはDB更新時にはコネクションとトランザクションの開始、コミットは1つづつにした方が良いです。 あ、このソースは単純に並び換えただけなので、このままで動くかどうかは検証していません。 | ||||
|
投稿日時: 2009-03-05 00:40
かずいさんが既に解説してくれていますが、
コネクションが複数あるということは、 「別の接続」という事ですので、それは別の人が接続しているのと同じような状況になります。 同様にトランザクションが複数あるということは 「別のトランザクション」という事ですので、銀行の処理と支店の処理が独立したトランザクションになってしまいます。 これは言ってみれば銀行の更新処理と支店の更新処理が別々に管理されてしまう事になってしまいます。 関連のある更新処理であれば「ひとつのトランザクション」というくくりにまとめて、 失敗した場合はどちらで失敗したにせよ、その「ひとつのトランザクション」をまるごとロールバックすれば、 そのトランザクションに含まれている更新処理を全部なかったことにする。 という手法もとれるということです。 かずいさんも「基本的に」とおっしゃっているように例外はありえますが、 今回ぐらいの2テーブルに1件ずつということであれば、1トランザクションでいいでしょう。 | ||||
|
投稿日時: 2009-03-05 09:43
ありがとうござます。
コネクションとトランザクションを1つのくくりにすることでうまくいきました。 |
1