前述したように、データ バインド コントロールは、データ ソースに渡された値を独立したキー、値 (新しい値)、および OldValues ディクショナリに保存します。デフォルトでは、SqlDataSource と ObjectDataSource は OldValues フィールドを無視し、キーと値のみを使用します。この動作は、データ ソースの ConflictDetection プロパティによって検出されます。このプロパティは、デフォルトで OverwriteChanges に設定されています。 OverwriteChanges パターンは、「レコードを更新または削除するために主キーの値のみを照合する」ことを意味します。この操作は、レコードの更新または削除では、レコードの基礎となる値が変更されたかどうかを考慮しないことを意味します。通常の状況では、データ行の値が最初に選択された値と正確に一致する場合にのみ、更新または削除操作が成功することが理想的な状態です。この理想的な状況では、行を選択してから更新するまでの間に別のユーザーが行を更新すると、更新操作は失敗します。データ ソースは、ConflictDetection プロパティを CompareAllValues に設定することによって、この操作もサポートします。このモードでは、データ ソースはコマンドまたはメソッドに OldValues を適用し、これらの値を使用して、更新または削除操作がレコードのすべての値と一致する必要があることを確認してから更新または削除します。記録。また、OldValuesParameterFormatString プロパティを有効な .NET Framework コンポーネント形式文字列 ("original_{0}" など) に設定して、OldValues および Keys ディクショナリ内のパラメータの名前を変更して NewValues パラメータと区別する方法を指定する必要があります。
次のコード例は、OverwriteChanges モードと CompareAllValues モードで SqlDataSource コントロールによって使用される一般的な SQL コマンドを示しています。 ID フィールドは主キー フィールドであるとみなされます。後者のコマンドは、主キーだけではなく、WHERE 句内のデータ行のすべての生の値を比較することに注意してください。この場合、データ ソースの OldValuesParameterFormatString を「original_{0}」に設定する必要があります。
[連絡先]から[ID]、[名前]、[住所]を選択
-- 変更の上書き
UPDATE [連絡先] SET [名前] = @Name、[アドレス] = @Address WHERE [ID] = @ID
DELETE FROM [連絡先] WHERE [ID] = @ID
-- CompareAllValues
UPDATE [連絡先] SET [名前] = @Name、[アドレス] = @Address WHERE [ID] = @original_ID
AND [名前] = @original_Name AND [アドレス] = @original_Address
DELETE FROM [連絡先] WHERE [ID] = @original_ID AND [名前] = @original_Name
AND [Address] = @original_Address
OldValues は挿入操作には必要なく、ConflictDetection は更新操作と削除操作にのみ意味があることに注意してください。
次の例は、競合が発生した場合の動作を示しています。このサンプルを実行するには、サンプルの 2 つのインスタンスを 2 つの別々のブラウザ ウィンドウで開く必要があります ([サンプルの実行] を 2 回クリックします)。次に、両方のフォームの同じ行にある「編集」ボタンをクリックして、行を編集モードにします。最初のウィンドウで値を変更し、「更新」をクリックします。更新が成功したことに注意してください。 2 番目のウィンドウで、行に新しい値を入力し、[更新] をクリックします。基になるデータ行の値は最初の更新操作によってすでに変更されているため、この更新操作は成功しません。この例では、Updated または Deleted イベント パラメーターの AffectedRows プロパティをチェックします。このプロパティは 0 であり、競合が発生していることを確認します。
<スクリプト runat="サーバー">
Protected Sub SqlDataSource1_Updated(オブジェクトとしての送信者、SqlDataSourceStatusEventArgs としての e)
e.AffectedRows = 0 の場合
Response.Write("行が変更されました、更新は中止されました<br />")
終了の場合
End Sub
Protected Sub SqlDataSource1_Deleted(sender As Object、e As SqlDataSourceStatusEventArgs)
e.AffectedRows = 0 の場合
Response.Write("行が変更されました、削除は中止されました<br />")
終了の場合
エンドサブ
</script>
テンプレート化された UI を使用して更新または削除を行う場合、バインド構文を使用した双方向データ バインディング フィールドの古い値が保持されます。削除の場合、これは、ItemTemplate のデータ バインドされた値にバインド構文を使用する必要があることを意味します。その目的は、削除操作に必要な古い値を保持することです。次の例は、この手法を示しています。
<コラム>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<アイテムテンプレート>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("ContactID") %>'></asp:Label>
</アイテムテンプレート>
<アイテムテンプレートの編集>
<asp:Label ID="Label3" runat="server" Text='<%# Eval("ContactID") %>'></asp:Label>
</EditItemTemplate>
</asp:テンプレートフィールド>
<アイテムテンプレート>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("ContactName") %>'></asp:Label>
</アイテムテンプレート>
<アイテムテンプレートの編集>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("ContactName") %>'></asp:TextBox>
</EditItemTemplate>
</asp:テンプレートフィールド>
</コラム>
</asp:GridView>
基礎となるデータが変更されたことをユーザーに通知し、変更された値をユーザーに表示し、ユーザーが操作を送信するか放棄するかを選択できるようにすることで、競合検出エラーを穏やかに処理できます。次の例は、競合検出を処理する可能な方法の 1 つを示しています。詳細ビューの RowUpdated イベント パラメーターには、ユーザーが入力した値の検出に使用できるディクショナリが渡されることに注意してください。このイベント パラメーターの KeepInEditMode プロパティを設定して、ユーザーが競合の処理方法を決定する間、DetailsView を編集モードに保つこともできます。この例では、前の例と同様のアプローチをテストし、2 つのウィンドウを同時に開いて競合する更新を作成します。
Protected SubDetailsView1_ItemUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewUpdatedEventArgs)
e.AffectedRows = 0 の場合
'DetailsView を編集モードにしてデータベースと同期します e.KeepInEditMode = True
詳細ビュー1.DataBind()
' ユーザーが入力した値をDetailsViewに再入力します
テキストボックスとして薄暗くする
t = 詳細ビュー 1.行(1).セル(1).コントロール(0)
t.Text = e.NewValues("注文日")
t = 詳細ビュー 1.行(2).セル(1).コントロール(0)
t.Text = e.NewValues("Shipcountry")
ErrorPanel.Visible = True
それ以外
ErrorPanel.Visible = False
終了の場合
End Sub
Protected SubDetailsView1_ModeChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewModeEventArgs)
e.CancelingEdit = True かつ ErrorPanel.Visible = True の場合
ErrorPanel.Visible = False
終了の場合
End Sub が
場合も状況は似ています
。データ ソースの ConflictDetection プロパティが CompareAllValues に設定されているため、データ ソースは Contact オブジェクトの各フィールドの生の値を受け入れる UpdateContact オーバーロードを検索することに注意してください。
DataObjectTypeName プロパティと CompareAllValues を一緒に使用することもできます。この場合、ObjectDataSource は 2 つのパラメーター (両方とも Contact) のみを受け入れる UpdateContact オーバーロードを探します。最初のパラメータは新しい値を格納する Contact オブジェクトで、2 番目のパラメータは古い値を格納する Contact オブジェクトです。