LINQ to SQL では、オプティミスティック コンカレンシー制御がサポートされています。 次の表では、LINQ to SQL ドキュメントのオプティミスティック コンカレンシーに適用される用語について説明します。
| 条件 | 説明 |
|---|---|
| コンカレンシー | 2 人以上のユーザーが同時に同じデータベース行を更新しようとする状況。 |
| コンカレンシーの競合 | 2 人以上のユーザーが同時に、競合する値を行の 1 つ以上の列に送信しようとする状況。 |
| コンカレンシー制御 | コンカレンシー競合を解決する手法。 |
| オプティミスティック コンカレンシー | 変更の送信を許可する前に、他のトランザクションが行の値を変更したかどうかを最初に調査する手法。 これと対照的なのが "ペシミスティック コンカレンシー制御" で、レコードをロックすることでコンカレンシーの競合を防ぎます。 オプティミスティック コントロールは、あるトランザクションが別のトランザクションに干渉する可能性が低いと考えられるため、そのように呼び出されます。 |
| 紛争解決 | データベースに再度クエリを実行し、相違点を調整することで、競合する項目を更新するプロセス。 オブジェクトが更新されると、LINQ to SQL 変更トラッカーは次のデータを保持します。 - データベースから取得され、更新チェックに使用された値。 - 後続のクエリの新しいデータベース値。 LINQ to SQL は、オブジェクトが競合しているかどうかを判断します (つまり、1 つ以上のメンバー値が変更されたかどうか)。 オブジェクトが競合している場合、LINQ to SQL は次に、競合しているメンバーを決定します。 LINQ to SQL が検出したメンバーの競合は、競合リストに追加されます。 |
LINQ to SQL オブジェクト モデルでは、次の両方の条件に該当する場合、 オプティミスティック コンカレンシーの競合 が発生します。
クライアントは、データベースに変更を送信しようとします。
クライアントが最後に値を読み取ってから、1 つ以上の更新チェック値がデータベースで更新されています。
この競合の解決には、競合しているオブジェクトのメンバーを検出し、そのオブジェクトに対して何を行うかを決定することが含まれます。
注
オプティミスティック コンカレンシー チェックに参加するのは、 Always または WhenChanged としてマップされたメンバーだけです。 Neverマークされたメンバーのチェックは実行されません。 詳細については、UpdateCheckを参照してください。
例
たとえば、次のシナリオでは、User1 はデータベースに対して行のクエリを実行して更新プログラムの準備を開始します。 User1 は、アルフレッド、マリア、および Sales の値を含む行を受け取ります。
User1 は、Manager 列の値をアルフレッドに、Department 列の値を Marketing に変更したいと考えています。 User1 がこれらの変更を送信する前に、User2 はデータベースに変更を送信しました。 そこで、アシスタント列の値が Mary に変更され、Department 列の値が Service に変更されました。
ここで、ユーザー 1 が変更を送信しようとすると、送信は失敗し、ChangeConflictException 例外がスローされます。 この結果は、アシスタント列と Department 列のデータベース値が予期した値ではないために発生します。 Assistant 列と Department 列を表すメンバーが競合しています。 次の表は、状況をまとめたものです。
| 状態 | マネージャー | アシスタント | 部門 |
|---|---|---|---|
| 元の状態 | アルフレッド | マリア | Sales |
| ユーザー 1 | アルフレッド | Marketing | |
| User2 | メアリー | サービス |
このような競合は、さまざまな方法で解決できます。 詳細については、「 方法: 変更の競合を管理する」を参照してください。
競合の検出と解決のチェックリスト
競合は、任意の詳細レベルで検出して解決できます。 極端な場合は、追加の考慮なしに、3 つの方法 ( RefreshModeを参照) のいずれかですべての競合を解決できます。 もう 1 つの極端な場合は、競合するすべてのメンバーに対して、競合の種類ごとに特定のアクションを指定できます。
オブジェクト モデル UpdateCheck オプションを指定または修正します。
詳細については、「方法: どのメンバーがコンカレンシー競合のテスト対象か指定する方法」を参照してください。
try/catch ブロックで SubmitChanges を呼び出す際に、例外をスローしたいタイミングを指定します。
詳細については、「方法 : コンカレンシー例外をいつスローするかを指定する」を参照してください。
取得したい競合の詳細を決定し、それに基づいて try/catch ブロックのコードを記述します。
詳細については、「方法: エンティティの競合情報を取得する」および「方法: メンバーの競合情報を取得する」を参照してください。
検出したさまざまな競合を解決する方法を
try/catchコードに含めます。詳細については、「方法: データベース値を保持して競合を解決する」、「方法: データベース値を上書きして競合を解決する」、および「方法: データベース値とマージして競合を解決する」を参照してください。
競合の検出と解決をサポートする LINQ to SQL 型
LINQ to SQL でのオプティミスティック コンカレンシーでの競合の解決をサポートするクラスと機能には、次のものが含まれます。