C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: 2テーブル以上のトランザクション処理


(過去ログ 77 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■45275 / inTopicNo.1)  2テーブル以上のトランザクション処理
  
□投稿者/ 匿名 (5回)-(2010/01/07(Thu) 19:51:45)

分類:[VB.NET/VB2005 以降] 

2つのテーブルにアクセスし、
2テーブル(テーブルA・テーブルB)の処理が完全に終了した場合のみコミット、
どちらか一方でも不具合があればロールバックしたいです。

現在、1テーブルのみで以下のようにしてますが、
単純に、「dRow = ds.Tables("テーブルA").NewRow」から
「da.Update(ds, "テーブルA") 」までをテーブルBに替えて
書き足すだけで良いのでしょうか?



−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Dim cn As New OleDb.OleDbConnection
Dim da As OleDb.OleDbDataAdapter
Dim ds As New DataSet
Dim cBuilder As New OleDb.OleDbCommandBuilder
Dim cnTran As OleDb.OleDbTransaction
Dim strSQL As String

cn.ConnectionString = "MDB情報"

Try
  da = New OleDb.OleDbDataAdapter(strSQL, cn)
  da.Fill(ds, "テーブルA")
  cn.Open()
  
  Dim dRow As DataRow

  dRow = ds.Tables("テーブルA").NewRow
  dRow("テーブルAのフィールド") = 値
  ds.Tables("テーブルA").Rows.Add(dRow)
  cBuilder.DataAdapter = da
  da.InsertCommand = cBuilder.GetInsertCommand
  cnTran = cn.BeginTransaction(IsolationLevel.ReadCommitted)
  da.InsertCommand.Transaction = cnTran
  da.Update(ds, "テーブルA")
  cnTran.Commit()
  cn.Close()

Catch ex As System.Data.OleDb.OleDbException

  If cnTran Is Nothing Then
  Else
    cnTran.Rollback()
  End If

Catch ex As Exception

  エラーメッセージ

End Try
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
引用返信 編集キー/
■45287 / inTopicNo.2)  Re[1]: 2テーブル以上のトランザクション処理
□投稿者/ もりお (158回)-(2010/01/08(Fri) 17:02:01)
No45275 (匿名 さん) に返信
> 単純に、「dRow = ds.Tables("テーブルA").NewRow」から
> 「da.Update(ds, "テーブルA") 」までをテーブルBに替えて
> 書き足すだけで良いのでしょうか?
単純に書き足すという言葉にどの様な意味が込められているのか量りかねる部分もありますが
そっくりそのままという意味ではおそらく出来ないです。
・DataAdapter のインスタンスをもうひとつ作らなくてはいけません。
・Connection.BeginTransaction は一回にしなければいけません。
概ね同じような処理という意味では良いとおもいます。

質問とはあまり関係ありませんが Connection オブジェクトは破棄を保証したほうが良いかと思
います。
Try
    ...
Catch ...
    ...
Finally
    cn.Dispose()
End Try

引用返信 編集キー/
■45288 / inTopicNo.3)  Re[2]: 2テーブル以上のトランザクション処理
□投稿者/ gtk2k (149回)-(2010/01/08(Fri) 17:17:52)
DataSetオブジェクトのdsにテーブルAとテーブルBがあるのであれば
NewRowからRows.Addのところを2つ書いて、Updateのところは
da.Update(ds);
とやれば1つのDataAdapterでできると思われ。
(すまん、今手元に開発環境がないため未検証)


引用返信 編集キー/
■45294 / inTopicNo.4)  Re[1]: 2テーブル以上のトランザクション処理
□投稿者/ はつね (1155回)-(2010/01/08(Fri) 20:03:48)
はつね さんの Web サイト
No45275 (匿名 さん) に返信
> 2テーブル(テーブルA・テーブルB)の処理が完全に終了した場合のみコミット、 
> どちらか一方でも不具合があればロールバックしたいです。 

Connectionに対してTransactionをはって
Try
   UPDATE テーブルA
   UPDATE テーブルB
   TransactionのCommit
Catch
   TransactionのRollBacj
End Try

参考URL
http://hatsune.wankuma.com/seminer/tokyo20/25.PNG

引用返信 編集キー/
■45295 / inTopicNo.5)  Re[2]: 2テーブル以上のトランザクション処理
□投稿者/ 匿名 (6回)-(2010/01/08(Fri) 20:51:32)
もりおさん、gtk2kさん、ありがとうございます。

> ・DataAdapter のインスタンスをもうひとつ作らなくてはいけません。
> ・Connection.BeginTransaction は一回にしなければいけません。

ちょうどこの部分で悩んでいました。

Dim da1,da2 As OleDb.OleDbDataAdapter と宣言して、
下記のようなソースを考えてみたのですが、
.BeginTransactionと.commitは対にしなければいけませんよね?
となると、どう対処したら良いのかがわかりません…


−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
cn.Open()

Dim dRow As DataRow

da1 = New OleDb.OleDbDataAdapter(strSQL, cn)
da1.Fill(ds, "テーブル1")
dRow = ds.Tables("テーブル1").NewRow
dRow("フィールド") = 値
ds.Tables("テーブル1").Rows.Add(dRow)
cBuilder.DataAdapter = da1
da1.InsertCommand = cBuilder.GetInsertCommand
cnTran = cn.BeginTransaction(IsolationLevel.ReadCommitted)
da1.InsertCommand.Transaction = cnTran
da1.Update(ds, "テーブル1")

da2 = New OleDb.OleDbDataAdapter(strSQL, cn)
da2.Fill(ds, "テーブル2")
dRow = ds.Tables("テーブル2").NewRow
dRow("フィールド") = 値
ds.Tables("テーブル2").Rows.Add(dRow)
cBuilder.DataAdapter = da2
da2.InsertCommand = cBuilder.GetInsertCommand
cnTran = cn.BeginTransaction(IsolationLevel.ReadCommitted)
da2.InsertCommand.Transaction = cnTran
da2.Update(ds, "テーブル2")

cnTran.Commit()

cn.Close()
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
引用返信 編集キー/
■45305 / inTopicNo.6)  Re[3]: 2テーブル以上のトランザクション処理
□投稿者/ gtk2k (150回)-(2010/01/09(Sat) 13:39:27)
2010/01/09(Sat) 13:44:09 編集(投稿者)

削除


引用返信 編集キー/
■45309 / inTopicNo.7)  Re[2]: 2テーブル以上のトランザクション処理
□投稿者/ もりお (159回)-(2010/01/09(Sat) 17:17:22)
No45295 (匿名 さん) に返信
> da1 = New OleDb.OleDbDataAdapter(strSQL, cn)
> da2 = New OleDb.OleDbDataAdapter(strSQL, cn)

テーブルが異なるので strSQL は同じではいけないです。
それぞれのテーブルに対する SQL をセットしてください。

> .BeginTransactionと.commitは対にしなければいけませんよね?
> となると、どう対処したら良いのかがわかりません…

BeginTransaction にて Transaction オブジェクトを作成して、それぞれのコ
マンドにセットしてください。

Dim cnTran As OleDbTransaction = cn.BeginTransaction(IsolationLevel.ReadCommitted)
da1.InsertCommand.Transaction = cnTran
da2.InsertCommand.Transaction = cnTran

オブジェクトの破棄を保証するために Using 句を用いるとこんな感じです。

Using cnTran As OleDbTransaction = cn.BeginTransaction(IsolationLevel.ReadCommitted)
    ...
    da1.InsertCommand.Transaction = cnTran
    da2.InsertCommand.Transaction = cnTran
    ...
End Using

記述の仕方の話です。

変数 dRow にテーブル1の新規行、テーブル2の新規行をセットしていますが

dRow = ds.Tables("テーブル1").NewRow
dRow = ds.Tables("テーブル2").NewRow

可読性を考えると別の変数を用意したほうが善いです。

Dim newRow1 As DataRow = ds.Tables("テーブル1").NewRow()
Dim newRow2 As DataRow = ds.Tables("テーブル2").NewRow()

変数 cBuilder も同じようにテーブル1用、テーブル2用にそれぞれの変数を作成し
てインスタンスをセットした方が善いです。

Dim commandBuilder1 As New OleDbCommandBuilder()
commandBuilder1.DataAdapter = da1
da1.InsertCommand = commandBuilder1.GetInsertCommand()

Dim commandBuilder2 As New OleDbCommandBuilder()
commandBuilder2.DataAdapter = da2
da2.InsertCommand = commandBuilder2.GetInsertCommand()

行数は増えますが、変数がテーブル1の状態かテーブル2の状態かを気にする
必要がなくなるので、処理に着目してコードを整理することが出来ます。
そうすることで、トランザクションが行われている場所を明確に出来ますし、
メソッドの分割もやりやすくなるかと思います。

' データベースからデータを取得する処理
Dim da1 As New OleDb.OleDbDataAdapter("...", cn)
da1.Fill(ds, "テーブル1")

Dim da2 As New OleDb.OleDbDataAdapter("...", cn)
da2.Fill(ds, "テーブル2")

' 新規データを作成する処理
Dim newRow1 As DataRow = ds.Tables("テーブル1").NewRow()
newRow1("フィールド") = "値"
ds.Tables("テーブル1").Rows.Add(newRow1)

Dim newRow2 As DataRow = ds.Tables("テーブル2").NewRow()
newRow2("フィールド") = "値"
ds.Tables("テーブル2").Rows.Add(newRow2)

' データベースを更新する処理
Dim commandBuilder1 As New OleDbCommandBuilder()
commandBuilder1.DataAdapter = da1
da1.InsertCommand = commandBuilder1.GetInsertCommand()

Dim commandBuilder2 As New OleDbCommandBuilder()
commandBuilder2.DataAdapter = da2
da2.InsertCommand = commandBuilder2.GetInsertCommand()

Using cnTran As OleDbTransaction = cn.BeginTransaction(IsolationLevel.ReadCommitted)
    da1.InsertCommand.Transaction = cnTran
    da2.InsertCommand.Transaction = cnTran
    Try 
        da1.Update(ds, "テーブル1")
        da2.Update(ds, "テーブル2")
        cnTran.Commit()
    Catch e As Exception
        cnTran.Rollback()
    End Try
End Using

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -