- - PR -
ADO.NETを利用したレコードロックの方法
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-09-21 14:48
こんにちは。お世話になります。
現在、VB.NETを開発環境としてADO.NETでのデータ更新などを開発しております。 その中でレコードロックの方法がどうしても分かりません。 どなたかご教授下さい。 現在私が記述したプログラムは以下のようになっています。 XXXXXの部分でエラーになってしまいます。 'DBオープン oraOLEDB.OpenDB(Cn) '注)コネクションを張る関数です 'トランザクションの開始 Tran = Cn.BeginTransaction 'レコードロック strSQL = "select * from SAIBAN where A = 'L' for update" Cmd = New OleDbCommand(strSQL, Cn) XXXXX COUNT = Cmd.ExecuteNonQuery() If COUNT = 1 Then '更新処理〜〜〜 End If 'コミット Tran.Commit() TranFLG = 0 | ||||||||
|
投稿日時: 2005-09-21 15:36
こんにちは、じゃんぬ です。
単に、OleDbTransaction と OleDbCommand が紐付いていないからでは? OleDbCommand.Transaction = OleDbConnection.BeginTransaction(); あと、Try 〜 Finally も実装しておいてください。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2005-09-21 15:37
SELECT文をExecuteNonQuery()に喰わせているのがいけないような気がします。
ExecuteReader()を使ってみたらどうでしょう? | ||||||||
|
投稿日時: 2005-09-21 15:44
ぼのぼのさん、フォローありがとうございます。(*_ _)
ありゃ? ExecuteNonQuery だと例外になりましたっけ? 確か、-1 が必ず返ってくるだけで例外にはならなかったような... で、今ソースをマジマジと見たんですが、 SELECT でカウントを取ろうとしているように見えます。 残念ですが、-1 が返ってくるだけで、カウントは取れないハズです... _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2005-09-21 15:55
あう、そうなんですか?すみません、試さずに投稿しちゃいました。 「XXXXXの部分でエラーになってしまいます。」とあったので、 ExecuteNonQueryがいけないのかなぁと… エラーの内容を書いてくれるとありがたかったですね。
あ、ほんとだ。気づきませんでしたw どちらにしろ、このロジックならExecuteReaderを使わないとですね。 | ||||||||
|
投稿日時: 2005-09-21 22:33
以前に ASP.NET の質問をされていますが、今回のコードは、ASP.NET で使用するのでしょうか?その場合、悲観ロックは「ロックされたまま」な状態を作り出すことがあります。
> XXXXXの部分でエラーになってしまいます。 エラーですか?例外が発生するのですか?エラーにしても例外にしても、その種類や書いてある内容は、重要な情報です。省略せずに書き出してください。 まぁ、想像は出来ますけど → これ その辺の使用例もよく見て、メソッドを書き換えておくことをお薦めします。 カウントとるんだったら SELECT COUNT(*) FROM ... ですよ。 (きっと、『UPDATE、INSERT、および DELETE ステートメントでの戻り値は、そのコマンドの影響を受ける行数です。』を勘違いしているんだろうな) カウントをとるだけでいいなら、ExecuteScalar でいいかと。 ってか、1件しかないときに、ってのなら、楽観ロックでも、オプティミスティック同時実行制御でも。。。ああ、でも、テーブル名が「SAIBAN」ってことは、採番か?だったらロックしたいってのも納得だけど、シーケンス使う方が。。。だいたい、Oracle だったら ODP.NET や、OracleClient 名前空間以下のクラスを使う方が。。。 _________________ | ||||||||
|
投稿日時: 2005-09-21 23:19
なつさん、こんばんわ。
更新処理がわからないのでなんともいえませんが。 「レコードを検索し、一件取得できたら更新」 というのなら、1度のSQL発行(update?)で足りそうな気がします。 (joinもするのかな?) はずしていたらすみません。 [ メッセージ編集済み 編集者: にわとり 編集日時 2005-09-21 23:24 ] | ||||||||
|
投稿日時: 2005-09-22 14:52
こんにちわ。ちょっと発散してきたので、一回まとめてみますね。
レコードのロックには、大別して2つの目的があると思います。 (1)あるユーザがあるレコードを掴んだ状態の時(編集中のステータスとでも言うのでしょうか)に、他のユーザがそのレコードを触れないようにする。 (2)ユーザが編集を終わって更新ボタンを押した後、UPDATE文を実行する際に、複数のユーザから同じレコードに対して同時に処理が走った場合、後続の処理が待たされないようにする。 今回のケースは、なつさんのコードを見る限り、(2)の方をやりたいように見えます。 もし(1)の方をやりたいのだとしたら、Jittaさんの仰る通り、ASP.NETでは悲観的ロックを使うべきではないです。 逆に(2)が目的なら、select count(*)じゃレコードをロックすることはできないですね。あとfor updateの後ろにnowaitをつけないと。後続の処理が待たされて良いなら、select for updateは必要ないです。にわとりさんの仰る通り、update文だけで十分です。 |