- PR -

Updateしたデータの件数の取得

投稿者投稿内容
hIzzI
会議室デビュー日: 2005/06/02
投稿数: 10
お住まい・勤務地: 名古屋市
投稿日時: 2006-03-25 15:32
データの更新件数を取得するためにSqlDataAdapterのUpdate()の戻り値を取得しているのですが、その値が常に-1となってしまいます。


SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();



int cnt = da.Update(ds); // cntは常に-1になってしまう


件数を取得するために他に何か記述が必要なのでしょうか?
よろしくお願いします。
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2006-03-25 16:39
NAL-6295です。

Updateを行う前に、該当のDataTableに保持しているDataRowの件数から、RowStateがUnchangedなDataRowの件数を差し引けば、更新対象の行数が取得できます。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-03-25 18:33
 例外が発生していませんか?私のところでは発生したのですが。


 DataSet には、複数のテーブルが存在し得ます。しかし、SqlDataAdapter には、1つの SqlCommand しか登録できません(SELECT, INSERT, UPDATE, DELETE それぞれ1つ)。つまり、Update メソッドで更新できるのは、1つのテーブルだけということです。
 ということは、DataSet、つまり複数のテーブルを引き渡して Update は出来ないはず、どのテーブルを更新すればいいのか混乱します。

 ということで、リファレンス(MSDN)を、調べます。
SqlDataAdapter.Update を見ると、DbDataAdapter.Update をオーバーライドしていることがわかります。
DbDataAdapter.Update を見ると、IDataAdapter.Update を実装していることがわかります。
IDataAdapter.Update を見ると、
引用:

指定された DataSet 内の Table という名前の DataTable に含まれる挿入行、更新行、または削除行に対して、INSERT、UPDATE、または DELETE ステートメントを個別に呼び出します。


 引数にテーブルを指定するか、テーブルの名称を "Table" にして、やってみてください。

〆 written by Jitta@わんくま同盟 on 2006/03/25
□ Microsoft MVP for Visual Developer ASP/ASP.NET October, 2005 - September, 2006
hIzzI
会議室デビュー日: 2005/06/02
投稿数: 10
お住まい・勤務地: 名古屋市
投稿日時: 2006-03-25 22:32
>NAL-6295様
返答ありがとうございます。

NAL-6295さんのおっしゃるように"更新対象"の件数はRowStateから取得できるのですが、"更新結果"の件数が取得出来ません。

更新結果件数が必要な理由として、例えばDELETE文を発行したときに実際にはデータベース側のテーブルに削除対象のレコードが既に存在していなくても、エラーとならないため、「レコードを実際に削除した」のか、「既に削除対象のレコードが存在していなかった」のかを区別するために更新結果件数を取得したいと考えています。
hIzzI
会議室デビュー日: 2005/06/02
投稿数: 10
お住まい・勤務地: 名古屋市
投稿日時: 2006-03-25 22:50
>Jitta様
返答ありがとうございます。

以下のように引数にDataTableオブジェクトを指定してみましたが結果はcnt=-1が返ってきてしまいます。
int cnt = da.Update(ds.Tables[0]); // 結果:cnt=-1

以下のようにDataSetを全く利用しない場合も同じでした。
DataTable dt = new DataTable();

int cnt = da.Update(dt); // 結果:cnt=-1


また、型付データセットクラスを作り(VS2005のxsdを利用して自動生成)、それをObjectDataSourceを通して利用し、
protected void ObjectDataSource1_Updated(object sender, ObjectDataSourceStatusEventArgs e)
{
    int cnt = e.AffectedRows; // 結果:cnt=-1
}
のようにイベントを利用して更新件数を取得してもcnt=-1となってしまいます。
<参考にしたコード>
http://www.asp.net/QuickStart/util/srcview.aspx?path=~/aspnet/samples/data/GridViewUpdatingEvent.src

[ メッセージ編集済み 編集者: hIzzI 編集日時 2006-03-25 22:52 ]
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2006-03-26 00:30
NAL-6295です。

引用:

更新結果件数が必要な理由として、例えばDELETE文を発行したときに実際にはデータベース側のテーブルに削除対象のレコードが既に存在していなくても、エラーとならないため、「レコードを実際に削除した」のか、「既に削除対象のレコードが存在していなかった」のかを区別するために更新結果件数を取得したいと考えています。



このような状況の場合DBConcurrencyExceptionが発生する前提(つまりContinueUpdateOnErrorが規定値)で話をしていました。
ただ、実際にUpdateの戻り値は更新された件数となっているので、更新されていない(つまり例外か何かが発生しているがそれを握りつぶしていて、その事実に気づいていない。)のでは無いでしょうか?

蛇足ですが、ContinueUpdateOnErrorがTrueの時は、エラーが発生しても更新が続行されますが、その際にエラーが発生したDataRowの配列についてはGetErrorsで取得できますので、事前にRowState = Unchangedでは無い行数からエラー対象の行数を差し引けば、結果的に更新が実行された行数にはなります。

[ メッセージ編集済み 編集者: NAL-6295 編集日時 2006-03-26 00:35 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-03-26 19:39
Updating イベントをハンドリングして、どの行で、どのような SQL 文が、どのようなパラメータとともに実行されようとしているのか、確認してください。

# 実行されていないような気もするけど
hIzzI
会議室デビュー日: 2005/06/02
投稿数: 10
お住まい・勤務地: 名古屋市
投稿日時: 2006-03-28 17:27
NAL-6295様、Jitta様、返答ありがとうございます。

いろいろ試してみましたが、AffectedRowsの結果が-1になってしまうのはObjectDataSourceを利用したときのようです。
SqlDataSourceを利用してUpdateやDeleteなどの操作をしたときには更新件数を取得することが出来ました。


調べた方法は、VS2005を利用して
<SqlDataSourceの場合>
1.aspxファイルを新規作成
2.サーバーエクスプローラからaspx上にテーブルをD&DしてSqlDataSourceを自動生成(SqlDataSource1)
3.ツールボックスからaspx上にGridViewをD&DしてGridViewコントロールを作成(GridView1)
4.GridView1のDataSourceIDにSqlDataSource1をセット
5.GridView1の共通タスクで「編集を有効にする」をチェック
6.SqlDataSource1のUpdatedイベントハンドラに「Response.Write(e.AffectedRows + "件");」
7.実行して編集を行う
結果⇒1件

<ObjectDataSourceの場合>
1.xsdファイルを新規作成
2.サーバーエクスプローラからxsd上にテーブルをD&DしてDataTableとTableAdapterを自動生成
3.TableAdapterの構成を表示し、「データテーブルの更新」のチェックをはずし、SQL文を再生成
4.aspxファイルを新規作成
5.ツールボックスからaspx上にObjectDataSourceをD&DしてObjectDataSourceコントロールを作成(ObjectDataSource1)
6.3で作成したSQL文をObjectDataSource1のSelectCommand,UpdateCommandに割り当てる
7.ツールボックスからGridViewをD&DしてGridViewコントロールを作成(GridView1)
8.GridView1のDataSourceIDにObjectDataSource1をセット
4.GridView1の共通タスクで「編集を有効にする」をチェック
5.SqlDataSource1のUpdatedイベントハンドラに「Response.Write(e.AffectedRows + "件");」
6.実行して編集を行う
結果⇒-1件

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