■GridViewの編集機能に同時実行時の処理を追加する (GridView04StepUp2.aspx)
GridViewからレコードを更新するとき楽観的ロックを適用するサンプルを作成します。このサンプルでは、GridViewから[更新]ボタンをクリックしたとき、他のユーザーからレコードがすでに更新されていれば「同時実行エラー」が発生した旨のメッセージを表示して再試行するように促します。
このサンプルは、以下のノウハウを習得することができます。
▼GridViewの更新処理に楽観的ロックを適用する方法


図 同時実行エラーを再現した例
1. 新規Webページ作成
ソリューションエクスプローラのプロジェクトの右クリックから[新しい項目の追加]を選択して、新規Webページ「GridView04StepUp2.aspx」を作成します。
2. コントロール作成
GridView04.aspxのデザイナからGridView1とSqlDataSource1のオブジェクトをコピーしたら、GridView04StepUp2.aspxのデザイナに貼り付けします。デザイナにGridView1とSqlDataSource1のオブジェクトが作成されます。ツールボックスの「標準」タブから[Label]をドラッグしたら、GridViewの上にドロップします。LabelのIDを「lblResult」に書き換えたら、Textプロパティを削除して「EnableViewState="False"」を追加します。
<asp:Label ID="lblResult" runat="server" EnableViewState="False"></asp:Label>
3. 楽観的ロックの組み込み
GridViewの「GridViewタスク」メニューから[データソース構成]をクリックします。データソース構成ウィザードが起動されたら指示に従って処理を続行します。「Selectステートメントの構成」が表示されたら、[詳細設定]ボタンをクリックします。「SQL生成の詳細オプション」が表示されたら、「オプティミステック同時実行制御」をチェックして[OK]をクリックします。

図 オプティミスティック同時実行制御をチェック
「Selectステートメントの構成」に戻ったら、[次へ]のボタンをクリックしてウィザードを完了させます。「選択されたデータソーススキーマを使用してGridView列フィールドとデータキーを再作成しますか?」のメッセージが表示されたら[いいえ]をクリックします。
4. イベントハンドラの追加
デザイナの右クリックから[コードの表示]を選択します。コードビューが表示されたら、「(全般)」のドロップダウンリストから[SqlDataSource1]、「(宣言)」のドロップダウンリストから[Updated]を選択します。SqlDataSource1_Updatedのイベントハンドラが作成されたら、次のコードを追加します。
Protected Sub SqlDataSource1_Updated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs) Handles SqlDataSource1.Updated
If e.AffectedRows = 0 Then
lblResult.Text = "同時実行エラーのため更新できませんでした!<br />再試行してください."
End If
End Sub
5. ブラウザに表示
VWD 2005のツールバーから[デバッグの開始]ボタンをクリックしてブラウザに表示します。ブラウザが起動されて、GridViewにCustomersテーブルが表示されます。ブラウザ(IE)の[ファイル]メニューから[新規作成]-[ウィンドウ]を選択して新規ウィンドウを開きます。2個のウィンドウが開いたら最初に開いたウィンドウを「ユーザー1」、2番目に開いたウィンドウを「ユーザー2」を想定します。次の手順で先頭レコードを更新して「同時実行エラー」を再現します。
ユーザー1:GridViewから先頭行の[編集]ボタンをクリックして編集モードに切り替える。
ユーザー2:GridViewから先頭行の[編集]ボタンをクリックして編集モードに切り替える。
ユーザー2:「ファックス」列に「(03)-3973-2222」を入力したら、[更新]ボタンをクリックする。
ユーザー1:「ファックス」列に「(03)-3973-1111」を入力したら、[更新]ボタンをクリックする。
ユーザー1:「同時実行エラーのため更新できませんでした! 再試行してください」が表示される。

図 2個のウィンドウを「ユーザー1」「ユーザー2」と想定して同時実行エラーを再現する
◆解説
データソース構成ウィザードの「SQL生成の詳細オプション」から「オプティミステック同時実行制御」をチェックすると、SqlDataSourceのUpdateCommandプロパティに次のようなUPDATEステートメントが格納されます。WHERE句ではUPDATEステートメントで更新するすべてのフィールドが変更されているか調べます。いずれかのフィールドが変更されていればUPDATEステートメントは実行されません。
UPDATE [Customers]
SET [CompanyName] = @CompanyName,
[ContactName] = @ContactName,
[Phone] = @Phone,
[Fax] = @Fax
WHERE [CustomerID] = @original_CustomerID
AND [CompanyName] = @original_CompanyName
AND [ContactName] = @original_ContactName
AND [Phone] = @original_Phone
AND [Fax] = @original_Fax"
UPDATEステートメントが実行されたかどうか調べるには、SqlDataSourceのUpdatedイベントハンドラを追加します。このイベントハンドラでは、SqlDataSouceStatusEventArgsのAffectedRowsプロパティを調べてレコードが更新されたかチェックします。AffectedRowsに「0」が格納されているときは、レコードが更新されていないことを意味します。ここでは、AffectedRowsが「0」のとき、レコードが他のユーザーから更新されたと想定(レコードが削除された場合も含まれます)して「同時実行エラー」を表示します。
Protected Sub SqlDataSource1_Updated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs) Handles SqlDataSource1.Updated
If e.AffectedRows = 0 Then
lblResult.Text = "同時実行エラーのため更新できませんでした!<br />再試行してください."
End If
End Sub
Customersテーブルのファックス(Fax)のフィールドがNullのとき、[編集]-[更新]ボタンをクリックすると「同時実行エラー」が表示されます。このエラーを回避するには以下のNoteを参照してください。
Note
|
列がNullのときレコードが更新されない不具合を回避するには データベースのフィールドがNull値を許可する設定になっているとき、GridVeiwからレコードを編集してもレコードが更新されない不具合があります。この不具合を回避するには、SqlDataSourceのUpdateCommandプロパティに格納されているUPDATEステートメントのWHERE句を修正する必要があります。 たとえば、CustomersテーブルのFaxフィールドがNull値を許可してときは、WHERE句にNULLのチェックを追加します。 UPDATE [Customers] SET [CompanyName] = @CompanyName, [ContactName] = @ContactName, [Phone] = @Phone, [Fax] = @Fax WHERE [CustomerID] = @original_CustomerID AND [CompanyName] = @original_CompanyName AND [ContactName] = @original_ContactName AND [Phone] = @original_Phone AND ([Fax] IS NULL OR [Fax] =
@original_Fax") |