- PR -

sqlExceptionとDBConcurrencyExceptionについて

1
投稿者投稿内容
Yoko
常連さん
会議室デビュー日: 2004/11/16
投稿数: 20
投稿日時: 2005-03-30 17:14
いつもお世話になっております。

ADO.NETとC#を用いてWindowsアプリケーションを作成しています。
DBはSQL SERVER2000 です。

同時実行をした場合のエラー処理について質問させてください。
例)
次のTABLE1を更新します。
取得時
tbl_id | name |
1  A
2  B
3  C
tbl_idが1のnameを次のように変更して登録します。
tbl_id | name |
1 AA
2  B
3  C

更新には次のようなプロシージャを用意しました。
CREATE PROCEDURE updateTABLE1
( @tbl_id int , @name char(10), @Orijinal_tbl_id int, @Orijinal_name char(10) )
AS
DECLARE @upd_error int
SET @upd_error = @@ERROR
UPDATE TABLE1
SET name = @name
WHERE (tbl_id = @Orijinal_tbl_id ) AND ( name = @Orijinal_name )
SET @upd_error = @@ERROR
IF @upd_error != 0
RAISERORR( 50001, 16, 1 )
RETURN @@ERROR

故意に同時実行になるようにテストしているのですが、
必ずDBConcurrencyExceptionにスローされてしまいます。

SQL SERVERが出した警告やエラーはsqlExeptionにスローしてほしいのですが
そうはならないのでしょうか?
(この同時実行違反のエラーもSQL SERVERから出されてると解釈しています)

※そもそも、sqlExeptionとDBConcurrencyExceptionが区別されている理由が
 よくわからないのです。
 SQL SERVERが警告またはエラーを返したときにスローされるのがsqlExeptionであるな らば、sqlExeptionで統一しても良いのでは?と思うのですが。。。

長々とすみません。
よろしくお願いいたします。

burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2005-03-30 17:31
ヘルプを見る限り
DBConcurrencyExceptionはSQL ServerではなくDataAdapterがスローすると書かれていますが、
DataAdapterを使用されているのでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-03-30 17:32
 まず、osqlで、更新する行が0になるようなUPDATE文を実行してみてください。

 エラーになりましたか?なりませんね。これより、このエラーはデータベースに起因するものではないことが理解できると思います。

 次に、MSDNの、DBConcurrencyExceptionクラスのページをみます。ここに、例外の派生元が書かれています。この中にSqlExceptionが入っていますか?いませんね。

 このページの説明をよく読むと、こう書いてあります。
引用:

挿入、更新、または削除のいずれかの操作を実行するたびに、その操作の影響を受ける行数を DataAdapter が検査し、影響を受ける行数が 0 になった場合にこの例外をスローします。


SqlCommand.Execute*メソッドでも、例外はでず、更新された行が0と返ってくるだけです。この例外は、DataAdapterが生成するものです。


[ メッセージ編集済み 編集者: Jitta 編集日時 2005-03-30 17:34 ]
Yoko
常連さん
会議室デビュー日: 2004/11/16
投稿数: 20
投稿日時: 2005-03-31 11:18
burton999さん、Jittaさんお返事ありがとうございました。

確かに更新にDataAdapterを使用しています。
以下のようにエラー処理していました。
try
{
dataAdapter.Update( dataSet );
}
catch( sqlExeption sqlerr )
{
Console.WriteLine( sqlerr.Message );

}
catch( DBConcurrencyException dberr )
{
Console.WriteLine( dberr.Message );

}
catch( Exception exerr )
{
Console.WriteLine( exerr.Message );
}

Jittaさんがおっしゃるとおり、
更新する行が0になるようなUPDATE文を実行してみましたが
確かにエラーにはなりませんでした。
つまり私が作成した更新プロシージャで
IF @upd_error != 0
RAISERORR( 50001, 16, 1 )
RETURN @@ERROR
この部分は通らないということですよね?

よくわかりました。ありがとうございました。

では、エラー処理の仕方としては
@@ERRORと@@ROWCOUNTを使用して、
処理が実際なされたかどうかの検査を行い、
ユーザーにメッセージを返すようにすれば、
sqlExceptionにスローさせることで統一できるのですね。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2005-03-31 21:01
引用:

2005-03-31 11:18より:

この部分は通らないということですよね?

では、エラー処理の仕方としては@@ERRORと@@ROWCOUNTを使用して、処理が実際なされたかどうかの検査を行い、ユーザーにメッセージを返すようにすれば、sqlExceptionにスローさせることで統一できるのですね。


 そうですね。通っていないはずです。
 う〜ん?
引用:

2005-03-30 17:14より:

SQL SERVERが出した警告やエラーはsqlExeptionにスローしてほしい
(この同時実行違反のエラーもSQL SERVERから出されてると解釈しています)


 SQL Serverが出している問題ではないのですから、DBConcurrencyExceptionで受ければいいのでは?

 または、DBConcurrencyExceptionが生成される状況というのが、一考の必要があるかと。
 この例外は、UPDATE、INSERT、DELETEの実行による影響を受けた行がゼロの時に生成されます。そして、同時実行制御をしている&更新対象の行が必ずあるという前提で、結果が0の時に生成されます。
 ここで、この前提が、個々のケースで絶対であるか、確認する必要があります。
 例えば、WHERE句の指定によって、対象の行がない場合、例外が生成されます。このケースがあり得るのか、あり得ないのか、検証する必要がないでしょうか。
 条件指定をユーザが行うのならば、対象行が0になる場合があり得ます。その場合に例外として扱い、エラーメッセージを出すのが正しいとは思いません。この場合、無視するか、「対象になる行はありませんでした」という普通のメッセージを出せばいいと思います。


[ メッセージ編集済み 編集者: Jitta 編集日時 2005-03-31 21:01 ]
Yoko
常連さん
会議室デビュー日: 2004/11/16
投稿数: 20
投稿日時: 2005-04-04 18:18
Jittaさんお返事ありがとうございました。

Jittaさんのおっしゃるとおり、
WHERE句の指定によって、対象の行がないケースがあり得るのか、あり得ないのか、よく検証してから、実装することにしました。

1

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