- - PR -
[VS.NET2005][C#][ADO.NET]RowUpdatedイベントのSqlRowUpdatedEventArgs.Rowプロパティ
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-04-26 18:41
【環境】
OS:WindowsXPPro IDE:VS.NET2005 DB:MSSQLServer2005 言語:C# AP:Windowsアプリ SQLDataAdapterを使って、複数レコードデータを格納したDataSetをDataBaseに更新 しようとしています。 対象Tableの主キー(ID)はIdentityを使って自動連番させるようにしています。 また、同時実行違反チェックの為に、timestamp型のカラムも用意しました。 DataBaseには、Insert/Update/Deleteの各処理に対応したストプロを作成し、 InsertCommand/UpdateCommand/DeleteCommandにはそれぞれのストプロを 呼び出すよう設定してあります。 Insert/Updateのストプロ内では、IDやtimestampの値を取得する為に、対象データを 再Selectするようにしていたのですが、ここで1つ問題が発生してしまいました。 CommandのUpdatedRowSourceプロパティは、デフォルトの「Both」のままにして いたのですが、このプロパティは「None」以外を指定するとデータの更新が 正常終了していても失敗していても、対象DataRowのRowStateを「Unchanged」に してしまうのです。 ※正確には、ストプロにデータを渡す前にRowStateを「Unchanged」にし、 戻ってきたデータをDataRowに反映させるとRowStateが「Modified」になる。 これでは、複数レコードある更新の途中でエラーが発生した場合に、DBへの 更新はRollBackできても、DataSetの中まではUpdate直前には戻せません。 (更新処理された行までのRowStateがUpdate前と変わってしまっている) そこで、こちらを参考に、RowUpdatedイベント内でIDとtimestampを取得しようと思ったのですが・・・ SqlRowUpdatedEventArgsのRowプロパティって読み込み専用ですよね? ※もちろんOleDbRowUpdatedEventArgsのRowプロパティも 試しに、こんな感じでコーディングしてみたのですが、やっぱりエラーが発生。
エラー内容:列 'IdentityKey' は読み取り専用です。 ※InsertCommand.UpdatedRowSourceには「None」を指定しています ※@ScopeIdentityは、ストプロでOUTPUTしていした、SCOPE_IDENTITY()の値を格納したパラメータです これって、MSDNの誤りなんでしょうか? ちなみに、会社に置いてある「プログラミングADO.NET」も読んでみたのですが、 (ちょっと古いですが「Microsoft公式解説書」って書いてある) こちらでも、RowUpdatedイベント内で取得したIDをOleDbRowUpdatedEventArgsの Rowプロパティを使って代入しろと書いてあるんですよね。 自分のプログラムに問題あり? どなたか、ADO.NETに強い方。お知恵を貸して下さい!! | ||||||||
|
投稿日時: 2007-04-26 20:03
設計思想の問題なのかも知れませんが、 私は更新でエラーが発生した後に、その DataSet を再利用して 更新するような設計はしません。 エラーが出たあとは、異常系の処理だけにしてしまいます。 正しく更新できるという保証はありませんから。
それはその通りですが、 e.Row["IdentityKey"] = という記述は、Row プロパティに値を設定しているわけではないですよね。 Row プロパティで返された DataRow のインデクサに代入しているだけです。 このインデクサは読み取り専用ではありません。 (プロパティが読み取り専用なら実行時エラーではなくコンパイルエラーになります) 代入したときに実行時エラーになるのは、 DataColumn.Readonly プロパティが true になっているからでしょう。 ID列の場合は Fill したときに true に設定されますから。 これを false にすれば代入は可能と思います。 | ||||||||
|
投稿日時: 2007-04-27 09:00
KIさん、こんにちは。
うぁ。お恥ずかしい。 仰る通りでした。
仰る事は重々承知しているつもりです。 が、エンドユーザーは良く言うのですよ。 『データを入力した後、エラーが出ても問題の場所さえ修正入力すれば再度登録できるようにして欲しい。 エラーが出たら今まで入力したものを再度入力させられるなんてありえない』 ・・・と(^^; そこで苦肉の策での、DataSetの再利用という訳です。 | ||||||||
|
投稿日時: 2007-04-27 09:22
ユーザー入力のチェックは、SqlDataAdapter.Update を呼び出す前に プログラムでチェックすべきだと思います。 「問題の場所さえ修正入力すれば」とユーザーさんがおっしゃるようなエラーなら 事前にチェックすることは可能ですよね。 例外はプログラムで予期できなかった致命的なエラーが起きた場合の処理と考えています。 |
1