次の方法で共有


SqlDataSource でオプティミスティック同時実行制御を実装する (C#)

作成者: Scott Mitchell

PDF のダウンロード

このチュートリアルでは、オプティミスティック同時実行制御の要点を確認し、SqlDataSource コントロールを使用して実装する方法について説明します。

はじめに

前のチュートリアルでは、SqlDataSource コントロールに挿入、更新、削除の機能を追加する方法について説明しました。 要点としては、これらの機能を提供するには、コントロールの InsertCommandUpdateCommand、または DeleteCommand プロパティに対応する INSERTUPDATE、または DELETE のSQL ステートメントを InsertParametersUpdateParameters、および DeleteParameters コレクションの適切なパラメーターと共に指定する必要があります。 これらのプロパティとコレクションは手動で指定できますが、データ ソースの構成ウィザードの [詳細設定] ボタンには、SELECT ステートメントに基づいてこれらのステートメントを自動的に作成する [INSERTUPDATE、および DELETE ステートメントの生成] チェック ボックスが用意されています。

[INSERTUPDATE、および DELETE ステートメントの生成] チェック ボックスに加えて、[SQL 生成の詳細オプション] ダイアログ ボックスには、[オプティミスティック同時実行制御を使用する] オプションが表示されます (図 1 を参照)。 オンにすると、自動生成された UPDATE および DELETE ステートメントの WHERE 句は、ユーザーが最後にデータをグリッドに読み込んだ後に基になるデータベース データが変更されていない場合にのみ、更新または削除を実行するように変更されます。

You Can Add Optimistic Concurrency Support from the Advanced SQL Generation Options Dialog Box

図 1: [SQL 生成の詳細オプション] ダイアログ ボックスからオプティミスティック コンカレンシーのサポートを追加できます

オプティミスティック同時実行制御の実装」に関するチュートリアルでは、オプティミスティック同時実行制御の基礎と、それを ObjectDataSource に追加する方法について説明しました。 このチュートリアルでは、オプティミスティック同時実行制御の基本について再度説明し、SqlDataSource を使用して実装する方法について説明します。

オプティミスティック同時実行制御のまとめ

複数の同時ユーザーが同じデータを編集または削除できる Web アプリケーションでは、あるユーザーが誤って別のユーザーによる変更を上書きする可能性があります。 「オプティミスティック同時実行制御の実装」チュートリアルでは、次の例を示しました。

Jisun と Sam の 2 人のユーザーが、ユーザーが GridView コントロールを使用して製品を更新および削除できるアプリケーションのページにアクセスしたとします。 ほぼ同じ時間に両者が "Chai" の編集ボタンをクリックしました。 Jisun は製品名を "Chai Tea" に変更し、[更新] ボタンをクリックします。 その結果は、データベースに送信される UPDATE ステートメントであり、(Jisun が更新したフィールドは ProductName の 1 つだけであっても) 製品の更新可能なフィールドが "すべて" 設定されます。 この時点において、データベースには、この特定の製品に対して "Chai Tea" という値、"飲料" カテゴリ、"Exotic Liquids" サプライヤーなどが含まれます。 しかし、Sam の画面の GridView には、編集可能な GridView 行にまだ "Chai" という製品名が表示されています。 Jisun の変更がコミットされてから数秒後、Sam がカテゴリを "調味料" に更新し、[更新] をクリックします。 これにより、製品名を "Chai" に設定し、CategoryID を対応する Condiments カテゴリ ID に設定する UPDATE ステートメントがデータベースに送信されます。 製品名に対する Jisun の変更は上書きされました。

図 2 は、このやりとりを示しています。

When Two Users Simultaneously Update a Record There s Potential for One User s Changes to Overwrite the Other s

図 2: 2 人のユーザーが同時にレコードを更新すると、1 人のユーザーの変更が他のユーザーを上書きする可能性があります (クリックすると、フルサイズの画像が表示されます)

このシナリオが起こらないようにするには、何らかのコンカレンシー制御 を実装する必要があります。 このチュートリアルの焦点であるオプティミスティック同時実行制御では、コンカレンシーの競合が随時発生する可能性がある一方で、そのような競合の大部分が発生しないという前提に基づいて機能します。 したがって、競合が発生した場合、オプティミスティック同時実行制御は、別のユーザーが同じデータを変更したため、変更を保存できないことをユーザーに通知するだけです。

Note

コンカレンシーの競合が多数あると見なされるアプリケーションや、そのような競合が許容できない場合は、代わりにペシミスティック同時実行制御を使用できます。 ペシミスティック同時実行制御の詳細については、「オプティミスティック同時実行制御の実装」チュートリアルを参照してください。

オプティミスティック同時実行制御は、更新または削除されるレコードの値が、更新または削除プロセスの開始時と同じであることを確認することによって機能します。 たとえば、編集可能な GridView で [編集] ボタンをクリックすると、レコードの値がデータベースから読み取られ、TextBoxes やその他の Web コントロールに表示されます。 これらの元の値は GridView によって保存されます。 後に、ユーザーが変更を加えて [更新] ボタンをクリックした後、使用する UPDATE ステートメントでは、元の値と新しい値を考慮し、ユーザーが編集を開始した元の値がデータベース内の値と同じ場合にのみ、基になるデータベース レコードを更新する必要があります。 図 3 は、この一連のイベントを示しています。

For the Update or Delete to Succeed, the Original Values Must Be Equal to the Current Database Values

図 3: 更新または削除を成功させるには、元の値が現在のデータベースの値と同じでなければならない (クリックするとフルサイズの画像が表示されます)

オプティミスティック同時実行制御を実装するには、さまざまな方法があります (オプションをいくつか簡単に確認するには、Peter A. Brombergオプティミスティック同時実行制御の更新ロジックに関するページを参照してください)。 SqlDataSource (およびデータ アクセス層で使用される ADO.NET 型指定されたデータセット) で使用される手法により、WHERE 句が拡張され、元のすべての値の比較が含まれます。 たとえば、次の UPDATE ステートメントは、現在のデータベース値が、GridView のレコードを更新するときに最初に取得された値と等しい場合にのみ、製品の名前と価格を更新します。 @ProductName および @UnitPrice パラメーターには、ユーザーが入力した新しい値が含まれます。一方、@original_ProductName@original_UnitPrice には、[編集] ボタンがクリックされたときに GridView に最初に読み込まれた値が含まれます。

UPDATE Products SET
    ProductName = @ProductName,
    UnitPrice = @UnitPrice
WHERE
    ProductID = @original_ProductID AND
    ProductName = @original_ProductName AND
    UnitPrice = @original_UnitPrice

このチュートリアルで説明するように、SqlDataSource でオプティミスティック同時実行制御を有効にすることは、チェック ボックスをオンにするのと同じくらい簡単です。

手順 1: オプティミスティック同時実行制御をサポートする SqlDataSource の作成

まず、SqlDataSource フォルダーから OptimisticConcurrency.aspx ページを開きます。 ツールボックスからデザイナーに SqlDataSource コントロールをドラッグし、その ID プロパティを ProductsDataSourceWithOptimisticConcurrencyに設定します。 次に、コントロールのスマート タグから [データ ソースの構成] リンクをクリックします。 ウィザードの最初の画面で、NORTHWINDConnectionString の操作を選択し、[次へ] をクリックします。

Choose to Work with the NORTHWINDConnectionString

図 4: NORTHWINDConnectionString の操作を選択します (クリックするとフルサイズの画像が表示されます)

この例では、ユーザーが Products テーブルを編集できるようにする GridView を追加します。 そのため、図 5 に示すように、[ステートメントの選択] 画面から Products テーブルをドロップダウン リストから選択し、ProductIDProductNameUnitPrice、および Discontinued 列を選択します。

From the Products Table, Return the ProductID, ProductName, UnitPrice, and Discontinued Columns

図 5: Products テーブルから、ProductIDProductNameUnitPrice、および Discontinued 列を返します (クリックするとフルサイズの画像が表示されます)

列を選択した後、[詳細設定] ボタンをクリックして、[SQL 生成の詳細オプション] ダイアログ ボックスを表示します。 [INSERTUPDATE、および DELETE ステートメントの生成] チェック ボックスと、[オプティミスティック同時実行制御を使用する] チェックボックスをオンにして、[OK] をクリックします (スクリーンショットについては、図 1 を参照してください)。 [次へ]、[完了] の順にクリックして、ウィザードを完了します。

データ ソースの構成ウィザードが完了したら、少し時間を取って、結果の DeleteCommand プロパティと UpdateCommand プロパティ、および DeleteParameters コレクションと UpdateParameters コレクションを確認します。 これを行う最も簡単な方法は、左下隅にある [ソース] タブをクリックして、ページの宣言構文を表示することです。 すると、次のような UpdateCommand 値があります。

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     [UnitPrice] = @original_UnitPrice AND
     [Discontinued] = @original_Discontinued

UpdateParameters コレクションには、次の 7 つのパラメーターがあります。

<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
    runat="server" ...>
    <DeleteParameters>
      ...
    </DeleteParameters>
    <UpdateParameters>
        <asp:Parameter Name="ProductName" Type="String" />
        <asp:Parameter Name="UnitPrice" Type="Decimal" />
        <asp:Parameter Name="Discontinued" Type="Boolean" />
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </UpdateParameters>
    ...
</asp:SqlDataSource>

同様に、 DeleteCommand プロパティと DeleteParameters コレクションは次のようになります。

DELETE FROM [Products]
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     [UnitPrice] = @original_UnitPrice AND
     [Discontinued] = @original_Discontinued
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
    runat="server" ...>
    <DeleteParameters>
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </DeleteParameters>
    <UpdateParameters>
        ...
    </UpdateParameters>
    ...
</asp:SqlDataSource>

[オプティミスティック同時実行制御の使用] オプションを選択すると、UpdateCommand プロパティと DeleteCommand プロパティの WHERE 句の拡張 (および各パラメーター コレクションへの追加パラメーターの追加) に加えて、他の 2 つのプロパティが調整されます。

データ Web コントロールが SqlDataSource の Update() または Delete() メソッドを呼び出すと、元の値が渡されます。 SqlDataSource の ConflictDetection プロパティが CompareAllValues に設定されている場合、これらの元の値がコマンドに追加されます。 OldValuesParameterFormatString プロパティは、これらの元の値パラメーターに使用される名前付けパターンを提供します。 データ ソースの構成ウィザードは、original_{0} を使用して、UpdateCommand および DeleteCommand プロパティの元の各パラメーター、また、UpdateParameters および DeleteParameters コレクションに対応する名前を付けます。

Note

SqlDataSource コントロールの挿入機能を使用していないため、 InsertCommand プロパティとその InsertParameters コレクションは削除して構いません。

NULL 値の正しい処理

残念ながら、オプティミスティック同時実行制御を使用する場合、データ ソースの構成ウィザードによって自動生成される拡張 UPDATE ステートメントおよび DELETE ステートメントは、NULL 値を含むレコードに対しては動作しません。 その理由を確認するために、SqlDataSource の UpdateCommand を見てみましょう。

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     [UnitPrice] = @original_UnitPrice AND
     [Discontinued] = @original_Discontinued

Products テーブルの UnitPrice 列には、NULL 値が含まれる可能性があります。 もしあるレコードの UnitPriceNULL 値である場合、WHERE 句の [UnitPrice] = @original_UnitPrice の部分は、NULL = NULL は必ず False を返すことから、"常に" False と評価されます。 したがって、NULL 値を含むレコードは編集または削除できません。 UPDATE ステートメントと DELETE ステートメントの WHERE 句が更新または削除する行を一切返さないためです。

Note

このバグは、2004 年 6 月に「SqlDataSource が不適切な SQL ステートメントを生成」で Microsoft に報告され、次のバージョンの ASP.NET で修正される予定であると報告されています。

これを修正するには、NULL 値を持つ可能性のある列すべてについて、UpdateCommand プロパティと DeleteCommand プロパティの両方の WHERE 句を手動で更新する必要があります。 一般に、[ColumnName] = @original_ColumnName を次に変更します。

(
   ([ColumnName] IS NULL AND @original_ColumnName IS NULL)
     OR
   ([ColumnName] = @original_ColumnName)
)

この変更は、宣言型マークアップ、プロパティ ウィンドウの UpdateQuery または DeleteQuery オプション、またはデータ ソースの構成ウィザードの [カスタム SQL ステートメントまたはストアド プロシージャの指定] オプションの [UPDATE] タブと [DELETE] タブを使用して直接行うことができます。 ここでも、この変更は、UpdateCommand または DeleteCommandWHERE 句に NULL 値を持つ可能性のある "すべての" 列に対して適用する必要があります。

これをこの例に適用すると、次の変更された UpdateCommandDeleteCommand の値になります。

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
        OR ([UnitPrice] = @original_UnitPrice)) AND
     [Discontinued] = @original_Discontinued
DELETE FROM [Products]
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
        OR ([UnitPrice] = @original_UnitPrice)) AND
     [Discontinued] = @original_Discontinued

手順 2: 編集オプションと削除オプションを持つ GridView を追加する

オプティミスティック同時実行制御をサポートするように SqlDataSource が構成されたので、残るは、このコンカレンシー コントロールを利用するページにデータ Web コントロールを追加することです。 このチュートリアルでは、編集と削除の両方の機能を提供する GridView を追加します。 これを行うには、ツールボックスからデザイナーに GridView をドラッグし、その IDProductsに設定します。 GridView のスマート タグから、それを手順 1 で追加した ProductsDataSourceWithOptimisticConcurrency SqlDataSource コントロールにバインドします。 最後に、スマート タグからの [編集を有効にする] オプションと [削除を有効にする] オプションをオンにします。

Bind the GridView to the SqlDataSource and Enable Editing and Deleting

図 6: GridView を SqlDataSource にバインドし、編集と削除を有効にします (クリックするとフルサイズの画像が表示されます)

GridView を追加した後に、ProductID BoundField を削除し、ProductName BoundField の HeaderText プロパティを Product に変更し、HeaderText プロパティが単に Price となるように UnitPrice BoundField を更新して、外観を構成します。 理想的には、編集インターフェイスを拡張して、ProductName 値の RequiredFieldValidator と、UnitPrice 値の CompareValidator を含めます (適切に書式設定された数値であることを確認するため)。 GridView の編集インターフェイスのカスタマイズの詳細については、「データ変更インターフェイスのカスタマイズ」チュートリアルを参照してください。

Note

GridView から SqlDataSource に渡された元の値はビュー状態に保存されるため、GridView のビュー状態を有効にする必要があります。

GridView に対してこれらの変更を行った後には、GridView および SqlDataSource 宣言型マークアップは次のようになります。

<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
    runat="server" ConflictDetection="CompareAllValues"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    DeleteCommand=
        "DELETE FROM [Products]
         WHERE [ProductID] = @original_ProductID
         AND [ProductName] = @original_ProductName
         AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
              OR ([UnitPrice] = @original_UnitPrice))
         AND [Discontinued] = @original_Discontinued"
    OldValuesParameterFormatString=
        "original_{0}"
    SelectCommand=
        "SELECT [ProductID], [ProductName], [UnitPrice], [Discontinued]
         FROM [Products]"
    UpdateCommand=
        "UPDATE [Products]
         SET [ProductName] = @ProductName, [UnitPrice] = @UnitPrice,
            [Discontinued] = @Discontinued
         WHERE [ProductID] = @original_ProductID
         AND [ProductName] = @original_ProductName
         AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
            OR ([UnitPrice] = @original_UnitPrice))
        AND [Discontinued] = @original_Discontinued">
    <DeleteParameters>
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </DeleteParameters>
    <UpdateParameters>
        <asp:Parameter Name="ProductName" Type="String" />
        <asp:Parameter Name="UnitPrice" Type="Decimal" />
        <asp:Parameter Name="Discontinued" Type="Boolean" />
        <asp:Parameter Name="original_ProductID" Type="Int32" />
        <asp:Parameter Name="original_ProductName" Type="String" />
        <asp:Parameter Name="original_UnitPrice" Type="Decimal" />
        <asp:Parameter Name="original_Discontinued" Type="Boolean" />
    </UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="Products" runat="server"
    AutoGenerateColumns="False" DataKeyNames="ProductID"
    DataSourceID="ProductsDataSourceWithOptimisticConcurrency">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
            SortExpression="Discontinued" />
    </Columns>
</asp:GridView>

オプティミスティック同時実行制御の動作を確認するには、2 つのブラウザー ウィンドウを開き、両方で OptimisticConcurrency.aspx ページを読み込みます。 両方のブラウザーで最初の製品の [編集] ボタンをクリックします。 1 つのブラウザーで製品名を変更し、[更新] をクリックします。 ブラウザーはポストバックされ、GridView は編集前モードに戻り、編集したレコードの新しい製品名が表示されます。

2 番目のブラウザー ウィンドウで価格を変更し (ただし、製品名は元の値のままにします)、[更新] をクリックします。 ポストバックでは、グリッドは編集前モードに戻りますが、価格の変更は記録されません。 2 番目のブラウザーには、新しい製品名が古い価格の最初のブラウザーと同じ値が表示されます。 2 番目のブラウザー ウィンドウで行われた変更は失われました。 さらに、コンカレンシー違反が発生したことを示す例外やメッセージがないため、変更は暗黙のうちに失われました。

The Changes in the Second Browser Window Were Silently Lost

図 7: 2 番目のブラウザー ウィンドウの変更が暗黙のうちに失われました (クリックするとフルサイズの画像が表示されます)

2 つ目のブラウザーの変更がコミットされなかった理由は、UPDATE ステートメントの WHERE 句によってすべてのレコードがフィルターで除外されたため、いずれの行にも影響を与えなかったためです。 UPDATE ステートメントをもう一度見てみましょう。

UPDATE [Products] SET
     [ProductName] = @ProductName,
     [UnitPrice] = @UnitPrice,
     [Discontinued] = @Discontinued
WHERE
     [ProductID] = @original_ProductID AND
     [ProductName] = @original_ProductName AND
     (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL) OR
        ([UnitPrice] = @original_UnitPrice)) AND
     [Discontinued] = @original_Discontinued

2 番目のブラウザー ウィンドウでレコードが更新されると、WHERE 句で指定された元の製品名が既存の製品名と一致しません (最初のブラウザーによって変更されたため)。 したがって、ステートメント [ProductName] = @original_ProductName は False を返し、UPDATE はいずれのレコードにも影響を与えません。

Note

削除も同様に機能します。 2 つのブラウザー ウィンドウが開いた状態で、まず特定の製品を 1 つで編集し、その変更を保存します。 一方のブラウザーで変更を保存した後、もう一方のブラウザーで同じ製品の [削除] ボタンをクリックします。 DELETE ステートメントの WHERE 句では元の値が一致しないため、削除は暗黙のうちに失敗します。

2 番目のブラウザー ウィンドウのエンド ユーザーの観点からは、[更新] ボタンをクリックすると、グリッドは編集前モードに戻りますが、変更は失われていました。 しかし、変更が反映されていないという視覚的なフィードバックはありません。 理想的には、ユーザーの変更がコンカレンシー違反のため失われた場合、それをユーザーに通知し、さらに、おそらくグリッドを編集モードに保つでしょう。 これを実現する方法を見てみましょう。

手順 3: コンカレンシー違反がいつ発生したかを判断する

コンカレンシー違反はユーザーが行った変更を拒否するので、コンカレンシー違反が発生した場合にはユーザーに警告を出すのが良いでしょう。 ユーザーに警告するには、Text プロパティに次のメッセージが表示される ConcurrencyViolationMessage という名前のページの上部に Label Web コントロールを追加します: 「別のユーザーによって同時に更新されたレコードを更新または削除しようとしました。 他のユーザーの変更を確認してから、更新または削除をやり直してください。」 Label コントロールの CssClass プロパティを [警告] に設定します。これは、赤、斜体、太字、および大きなフォントでテキストを表示する Styles.css で定義された CSS クラスです。 最後に、Label の Visible プロパティと EnableViewState プロパティを false に設定します。 これにより、Visible プロパティを明示的に true に設定したポストバックのみを除き、Label は非表示になります。

Add a Label Control to the Page to Display the Warning

図 8: Label コントロールをページに追加して警告を表示します (クリックするとフルサイズの画像が表示されます)

更新または削除を実行すると、GridView の RowUpdated および RowDeleted イベント ハンドラーは、要求された更新または削除をデータ ソース管理が実行した後に発生します。 これらのイベント ハンドラーから、操作の影響を受けた行の数を確認できます。 影響を受けたのが 0 行の場合は、ConcurrencyViolationMessage ラベルを表示します。

RowUpdated イベントと RowDeleted イベントの両方のイベント ハンドラーを作成し、次のコードを追加します。

protected void Products_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
    if (e.AffectedRows == 0)
    {
        ConcurrencyViolationMessage.Visible = true;
        e.KeepInEditMode = true;
        // Rebind the data to the GridView to show the latest changes
        Products.DataBind();
    }
}
protected void Products_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
    if (e.AffectedRows == 0)
        ConcurrencyViolationMessage.Visible = true;
}

どちらのイベント ハンドラーでも、e.AffectedRows プロパティを確認し、0 の場合は、ConcurrencyViolationMessage Label の Visible プロパティを true に設定します。 RowUpdated イベント ハンドラーでは、 KeepInEditMode プロパティを true に設定して、GridView に編集モードを維持するように指示します。 その際、他のユーザーのデータが編集インターフェイスに読み込まれるように、データをグリッドに再バインドする必要があります。 これを行うには、GridView の DataBind() メソッドを呼び出します。

図 9 に示すように、これら 2 つのイベント ハンドラーでは、コンカレンシー違反が発生するたびに非常に顕著なメッセージが表示されます。

A Message is Displayed in the Face of a Concurrency Violation

図 9: コンカレンシー違反が発生した場合にメッセージが表示される (クリックするとフルサイズの画像が表示されます)

まとめ

複数の同時ユーザーが同じデータを編集している可能性がある Web アプリケーションを作成する場合は、コンカレンシー制御オプションを検討することが重要です。 既定では、ASP.NET データ Web コントロールとデータ ソース コントロールはコンカレンシー制御を使用しません。 このチュートリアルで説明したように、SqlDataSource を使用したオプティミスティック同時実行制御の実装は比較的迅速かつ簡単です。 SqlDataSource は、自動生成された UPDATE および DELETE ステートメントに拡張 WHERE 句を追加するためのほとんどの作業を処理しますが、「NULL 値の正しい処理」セクションで説明されているように、NULL 値列の処理にはいくつかの微妙な点があります。

このチュートリアルで、SqlDataSource の検討は終了です。 残りのチュートリアルでは、ObjectDataSource と階層化アーキテクチャを使用したデータの操作に戻ります。

プログラミングに満足!

著者について

7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジに取り組んでいます。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。