ASP.NET GridViewのホームへ戻る

GridViewの編集機能に同時実行時の処理を追加する (GridView04StepUp2.aspx)

 

GridViewからレコードを更新するとき楽観的ロックを適用するサンプルを作成します。このサンプルでは、GridViewから[更新]ボタンをクリックしたとき、他のユーザーからレコードがすでに更新されていれば「同時実行エラー」が発生した旨のメッセージを表示して再試行するように促します。

 

このサンプルは、以下のノウハウを習得することができます。

 

GridViewの更新処理に楽観的ロックを適用する方法

 

 

 

 

 

  同時実行エラーを再現した例

 

 

1. 新規Webページ作成

 

ソリューションエクスプローラのプロジェクトの右クリックから[新しい項目の追加]を選択して、新規Webページ「GridView04StepUp2.aspx」を作成します。

 

 

2. コントロール作成

 

GridView04.aspxのデザイナからGridView1SqlDataSource1のオブジェクトをコピーしたら、GridView04StepUp2.aspxのデザイナに貼り付けします。デザイナにGridView1SqlDataSource1のオブジェクトが作成されます。ツールボックスの「標準」タブから[Label]をドラッグしたら、GridViewの上にドロップします。LabelIDを「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のツールバーから[デバッグの開始]ボタンをクリックしてブラウザに表示します。ブラウザが起動されて、GridViewCustomersテーブルが表示されます。ブラウザ(IE)[ファイル]メニューから[新規作成]-[ウィンドウ]を選択して新規ウィンドウを開きます。2個のウィンドウが開いたら最初に開いたウィンドウを「ユーザー1」、2番目に開いたウィンドウを「ユーザー2」を想定します。次の手順で先頭レコードを更新して「同時実行エラー」を再現します。

 

ユーザー1:GridViewから先頭行の[編集]ボタンをクリックして編集モードに切り替える。

ユーザー2:GridViewから先頭行の[編集]ボタンをクリックして編集モードに切り替える。

ユーザー2:「ファックス」列に「(03)-3973-2222」を入力したら、[更新]ボタンをクリックする。

ユーザー1:「ファックス」列に「(03)-3973-1111」を入力したら、[更新]ボタンをクリックする。

ユーザー1:「同時実行エラーのため更新できませんでした! 再試行してください」が表示される。

 

 

図 2個のウィンドウを「ユーザー1」「ユーザー2」と想定して同時実行エラーを再現する

 

 

◆解説

 

データソース構成ウィザードの「SQL生成の詳細オプション」から「オプティミステック同時実行制御」をチェックすると、SqlDataSourceUpdateCommandプロパティに次のような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ステートメントが実行されたかどうか調べるには、SqlDataSourceUpdatedイベントハンドラを追加します。このイベントハンドラでは、SqlDataSouceStatusEventArgsAffectedRowsプロパティを調べてレコードが更新されたかチェックします。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からレコードを編集してもレコードが更新されない不具合があります。この不具合を回避するには、SqlDataSourceUpdateCommandプロパティに格納されている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")

 

 

 

ASP.NET GridViewのホームへ戻る