- PR -

ADO.NETを利用したレコードロックの方法

投稿者投稿内容
なつ
会議室デビュー日: 2005/08/18
投稿数: 18
投稿日時: 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
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-09-21 15:36
こんにちは、じゃんぬ です。

引用:

なつさんの書き込み (2005-09-21 14:48) より:

現在私が記述したプログラムは以下のようになっています。
XXXXXの部分でエラーになってしまいます。


単に、OleDbTransaction と OleDbCommand が紐付いていないからでは?

OleDbCommand.Transaction = OleDbConnection.BeginTransaction();

あと、Try 〜 Finally も実装しておいてください。


_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2005-09-21 15:37
SELECT文をExecuteNonQuery()に喰わせているのがいけないような気がします。
ExecuteReader()を使ってみたらどうでしょう?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-09-21 15:44
ぼのぼのさん、フォローありがとうございます。(*_ _)

引用:

ぼのぼのさんの書き込み (2005-09-21 15:37) より:
SELECT文をExecuteNonQuery()に喰わせているのがいけないような気がします。
ExecuteReader()を使ってみたらどうでしょう?


ありゃ? ExecuteNonQuery だと例外になりましたっけ?
確か、-1 が必ず返ってくるだけで例外にはならなかったような...

で、今ソースをマジマジと見たんですが、
SELECT でカウントを取ろうとしているように見えます。
残念ですが、-1 が返ってくるだけで、カウントは取れないハズです...


_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2005-09-21 15:55
引用:

じゃんぬねっとさんの書き込み (2005-09-21 15:44) より:

ありゃ? ExecuteNonQuery だと例外になりましたっけ?
確か、-1 が必ず返ってくるだけで例外にはならなかったような...


あう、そうなんですか?すみません、試さずに投稿しちゃいました。
「XXXXXの部分でエラーになってしまいます。」とあったので、
ExecuteNonQueryがいけないのかなぁと…
エラーの内容を書いてくれるとありがたかったですね。

引用:

で、今ソースをマジマジと見たんですが、
SELECT でカウントを取ろうとしているように見えます。
残念ですが、-1 が返ってくるだけで、カウントは取れないハズです...


あ、ほんとだ。気づきませんでしたw
どちらにしろ、このロジックならExecuteReaderを使わないとですね。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-09-21 22:33
 以前に ASP.NET の質問をされていますが、今回のコードは、ASP.NET で使用するのでしょうか?その場合、悲観ロックは「ロックされたまま」な状態を作り出すことがあります。


> XXXXXの部分でエラーになってしまいます。
エラーですか?例外が発生するのですか?エラーにしても例外にしても、その種類や書いてある内容は、重要な情報です。省略せずに書き出してください。

 まぁ、想像は出来ますけど → これ
その辺の使用例もよく見て、メソッドを書き換えておくことをお薦めします。


カウントとるんだったら SELECT COUNT(*) FROM ... ですよ。
(きっと、『UPDATE、INSERT、および DELETE ステートメントでの戻り値は、そのコマンドの影響を受ける行数です。』を勘違いしているんだろうな)

カウントをとるだけでいいなら、ExecuteScalar でいいかと。


 ってか、1件しかないときに、ってのなら、楽観ロックでも、オプティミスティック同時実行制御でも。。。ああ、でも、テーブル名が「SAIBAN」ってことは、採番か?だったらロックしたいってのも納得だけど、シーケンス使う方が。。。だいたい、Oracle だったら ODP.NET や、OracleClient 名前空間以下のクラスを使う方が。。。

_________________
にわとり
ベテラン
会議室デビュー日: 2001/08/30
投稿数: 70
投稿日時: 2005-09-21 23:19
なつさん、こんばんわ。

引用:

なつさんの書き込み (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


更新処理がわからないのでなんともいえませんが。
「レコードを検索し、一件取得できたら更新」
というのなら、1度のSQL発行(update?)で足りそうな気がします。
(joinもするのかな?)
はずしていたらすみません。

[ メッセージ編集済み 編集者: にわとり 編集日時 2005-09-21 23:24 ]
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2005-09-22 14:52
こんにちわ。ちょっと発散してきたので、一回まとめてみますね。

レコードのロックには、大別して2つの目的があると思います。

(1)あるユーザがあるレコードを掴んだ状態の時(編集中のステータスとでも言うのでしょうか)に、他のユーザがそのレコードを触れないようにする。

(2)ユーザが編集を終わって更新ボタンを押した後、UPDATE文を実行する際に、複数のユーザから同じレコードに対して同時に処理が走った場合、後続の処理が待たされないようにする。

今回のケースは、なつさんのコードを見る限り、(2)の方をやりたいように見えます。
もし(1)の方をやりたいのだとしたら、Jittaさんの仰る通り、ASP.NETでは悲観的ロックを使うべきではないです。
逆に(2)が目的なら、select count(*)じゃレコードをロックすることはできないですね。あとfor updateの後ろにnowaitをつけないと。後続の処理が待たされて良いなら、select for updateは必要ないです。にわとりさんの仰る通り、update文だけで十分です。

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