- PR -

1トランザクション内でSELECTとUPDATE

投稿者投稿内容
kes
ベテラン
会議室デビュー日: 2004/08/10
投稿数: 67
投稿日時: 2005-02-05 17:37
VB.NETのOleDbでOracleにアクセスしているのですが、
DataReaderでDBからデータを読み込んで、リーダがOpenの状態のまま、同じコネクション、トランザクションでUPDATEやINSERTを実行しようとすると、「先にリーダーを閉じろ」、と怒られてしまいます。
リーダーで取得した行の内容を元にUPDATEをかけたいような場合でも、いったんローカルのデータテーブルか何かに落としてから、リーダーを閉じて、それからローカルのテーブルのデータを使ってUPDATEするしかないのでしょうか。
非常に不便な気がするのですが。

別のコネクションを作れば開いたままでも問題ありませんが、もっと前の別の処理でUPDATEをかけてコミットしていない場合、別のコネクションでリードした内容には変更が反映されていないので、これでは使えません。

どなたか良い方法をご存じないでしょうか。


よろしくお願いいたします。
松竹梅
会議室デビュー日: 2002/12/26
投稿数: 6
投稿日時: 2005-02-05 20:40
 SDKドキュメントのとおり、DataReaderがオープンされた状態で、そのコネクションは
他で使用できません。
 ので、DataSet を使われたらいかがですか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-02-05 21:24
 同じコネクションでコマンドを作成してください。トランザクションを張って、コネクションをクローズせずに、Updateをします。
_________________
kes
ベテラン
会議室デビュー日: 2004/08/10
投稿数: 67
投稿日時: 2005-02-06 15:17
回答ありがとうございます。

お2人のおっしゃってることが違うような気がするのですが・・・

>同じコネクションでコマンドを作成してください。トランザクションを張って、コネクション
>をクローズせずに、Updateをします。

コネクションは閉じずに、同じトランザクションを指定してExecuteReaderとExecuteNonqueryをやっているつもりですが、だめなようです。
とにかくReaderをCloseしないことには、ほかの事をさせてくれないようです。
それとも何か他にするべきことがあるのでしょうか。


すみませんが、よろしくお願いいたします。
xxななおxx
ベテラン
会議室デビュー日: 2005/01/18
投稿数: 61
お住まい・勤務地: 東京(練馬)
投稿日時: 2005-02-06 16:53
すいません。横槍かも知れませんが、、。

"松竹梅さん"の言ってることはMSDNの↓
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpcontheadonetdatareader.asp
に似てる内容だと思います。

----MSDN抜粋-------
DataReader が開いている間、Connection はその DataReader によって排他的に使用されています。元の DataReader が終了するまでは、その Connection に対してはどのコマンドも実行できません。別の DataReader を作成することもできません。
-----------------

なので、「DataReaderでは無く、DataAdapterを使ってDataSetを検索・更新に使用したらどうですか?」という提案だと思います。
私もそう思いますが・・。?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-02-06 19:04
引用:

kesさんの書き込み (2005-02-06 15:17) より:

コネクションは閉じずに、同じトランザクションを指定してExecuteReaderとExecuteNonqueryをやっているつもりですが、だめなようです。
とにかくReaderをCloseしないことには、ほかの事をさせてくれないようです。
それとも何か他にするべきことがあるのでしょうか。


だから、Readerはクローズしてください。しかし、Connectionは、クローズしないでください。

 とはいえ、SELECTとUPDATEのトランザクションを同じにすることに意義を見いだせません。FOR UPDATEでしょうか。しかし、こういう使い方はするべきではないと思います。更新日時を持つなどで、誰かが更新していたら更新しないようにできます。このとき、DataAdapter.Updateを使うと、同時更新エラー、みたいな例外が発生します。
_________________
kes
ベテラン
会議室デビュー日: 2004/08/10
投稿数: 67
投稿日時: 2005-02-06 23:09
すみません、SQLもVB.NETも最近やり始めたもので、何をするにも常識がわかりません。

もっと具体的にやろうとしていることを書きますと、
在庫のデータをメンテナンスしたときの処理なんですが、その在庫の情報を持つテーブルと、その在庫が含まれている日ごと、月ごとの締め切りデータを更新したいのです。
まず最初に在庫情報のテーブルに対するUPDATEをかけ、その後、UPDATEした在庫情報を読みながら、その在庫と関連する締めデータにUPDATEをかけようとしてるのですが、そこでReaderを閉じろというエラーになります。

一連の処理が正常に終わらないとCOMMITすることは許されないので、同じトランザクション内でUPDATE→UPDATEしたものをSELECT→別のテーブルをUPDATEというふうにしたのですが、そもそもこういうやり方がおかしい、ということでしょうか。

このような処理を組む場合はどのようなロジックにするのがいいのでしょうか。



すみませんがよろしくお願いします。
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2005-02-07 00:56
引用:

在庫のデータをメンテナンスしたときの処理なんですが、その在庫の情報を持つテーブルと、その在庫が含まれている日ごと、月ごとの締め切りデータを更新したいのです。
まず最初に在庫情報のテーブルに対するUPDATEをかけ、その後、UPDATEした在庫情報を読みながら、その在庫と関連する締めデータにUPDATEをかけようとしてるのですが、そこでReaderを閉じろというエラーになります。



在庫情報のUPDATE以外はDB側(SQL)でやるべきだと思う。
パフォーマンス的な問題がなければ「その在庫が含まれている日ごと、月ごとの締め切りデータ」のテーブルの存在すらいらないかもしれない。

トリガとかビューとかその辺を調べてみてください。
データ処理や同期はDB側で完結させたほうが楽です。そのためのDBですし。

スキルアップ/キャリアアップ(JOB@IT)