競合の処理

同期中、同期先プロバイダは、ProcessChangeBatch (マネージ コードの場合) メソッドまたは ProcessChangeBatch (アンマネージ コードの場合) メソッドを介して、同期元プロバイダから変更バッチを受け取ります。以降、このリストに起因するすべての競合は、同期先プロバイダで検出する必要があります。

競合検出

同期中に発生する可能性のある競合には、同時実行の競合と制約の競合の 2 種類があります。

同時実行の競合

同時実行の競合は、同期先レプリカの変更のバージョンが、同期元レプリカのナレッジに存在しない場合に発生します。これらの競合は、同期対象の同じ項目に対して 2 つの操作 (更新と削除や、更新と更新など) が影響を及ぼすことによって起こります。

通常、同期先プロバイダは、Sync Framework の Change Applier オブジェクトを使用して、同時実行の競合を検出します。Change Applier は、NotifyingChangeApplier オブジェクト (マネージ コードの場合) または ISynchronousNotifyingChangeApplier インターフェイス (アンマネージ コードの場合) で表されます。Change Applier を使用して変更を検出するには、同期元プロバイダから送信された変更バッチ内の各項目について、同期先プロバイダがバージョン情報を提供する必要があります。これには、次の 2 とおりの方法があります。

  • 同期先プロバイダが、同期元プロバイダから送信された変更バッチに対応する変更の一覧を構築します。同期元プロバイダの変更バッチに含まれる各項目について、同期先プロバイダは、その一覧に項目を追加します。一覧には、同期先レプリカにおける、該当する項目のバージョンが格納されます。Change Applier には、この一覧が渡されます。Change Applier は、この一覧を使用して、各項目の同期先のバージョンが、同期元レプリカのナレッジに存在するかどうかを確認します。

  • 同期先プロバイダが、同期先バージョンの一覧を Change Applier に渡すことはありません。代わりに、同期先プロバイダは、TryGetDestinationVersion (マネージ コードの場合) メソッドまたは ISynchronousNotifyingChangeApplierTarget::GetDestinationVersion (アンマネージ コードの場合) メソッドを実装します。このメソッドが、同期元プロバイダの変更バッチに含まれる各項目につき 1 回呼び出されます。

競合を検出するために Change Applier がどのようなことを実行しているのかをより詳しく理解するために、同期先プロバイダが同期元プロバイダから変更バッチを受け取るシナリオを考えてみてください。競合を検出するには、変更バッチ内の各項目について次の手順を実行する必要があります。

  1. 同期先プロバイダは、同期先レプリカの項目のバージョンが、同期元レプリカのナレッジに存在するかどうかを確認します。

  2. 同期先レプリカのバージョンが同期元レプリカのナレッジに存在しない場合、そのオブジェクトは競合していると考えられます。

制約の競合

制約の競合は、項目が持つ制約 (フォルダの関係や、ファイル システムにおいて、まったく同じ名前が付けられたデータの場所など) に違反する競合です。

制約の競合の検出は、レプリカで使用されているデータ ストアに依存するため、こうした競合の種類をプロバイダ側で検出する必要があります。たとえば、階層構造を持ったファイル システムを表すプロバイダは、保存データに適用される、ストア固有の制約 (場所、名前、サイズなど) を検出できなければなりません。

競合の解決

競合は、セッション中に発生するすべての競合に適用される解決方法を定義するか、競合ごとに 1 回だけ発生するイベントを処理することによって解決できます。

競合の解決方法の設定

セッション中に発生するすべての競合に適用されるポリシーを指定するには、アプリケーションから、同期先プロバイダの ConflictResolutionPolicy プロパティ (マネージ コードの場合) または ISyncSession::Start メソッド (アンマネージ コードの場合) で競合の解決方法を指定します。

競合の解決アクションの設定

発生する個々の競合に対して、その解決アクションを動的に設定するには、アプリケーションで、ItemConflicting (マネージ コードの場合) または ISyncCallback::OnConflict (アンマネージ コードの場合) を使用して、項目競合イベントを処理します。このイベントは、競合の解決方法が ApplicationDefined (マネージ コードの場合) または CRP_NONE (アンマネージ コードの場合) に設定されている場合にのみ発生します。

マネージ コード : ItemConflicting が発生すると、イベント ハンドラには、競合する 2 つの変更のメタデータおよび項目データを保持する ItemConflictingEventArgs オブジェクトが渡されます。イベント ハンドラで、2 つの競合を調査して、メタデータまたは項目データに変更を加え、さらに、SetResolutionAction メソッドを使用して、競合の解決アクションを設定します。その後、Sync Framework によって競合が処理され、同期元または同期先のプロバイダに対して適切な呼び出しが行われて、変更が適用されます。

アンマネージ コード : ISyncCallback::OnConflict が発生すると、イベント ハンドラには、競合する 2 つの変更のメタデータおよび項目データを保持する IChangeConflict オブジェクトが渡されます。イベント ハンドラで、2 つの競合を調査して、メタデータまたは項目データに変更を加え、さらに、IChangeConflict::SetResolveActionForChange メソッドを使用して、競合の解決アクションを設定します。その後、Sync Framework によって競合が処理され、同期元または同期先のプロバイダに対して適切な呼び出しが行われて、変更が適用されます。

競合の解決

Sync Framework には、競合に対する一連の解決アクションが用意されており、それらを利用することで、解決処理の大半を自動的に行うことができます。項目競合イベント ハンドラで直接変更を処理することによって競合を解決することもできます。

競合の解決方法 説明 利用形態 (セッション ポリシーとして/項目のアクションとして)

同期元優先

同期元レプリカが常に優先されます。これは、同期先レプリカを信頼しないようにする、読み取り専用の同期ソリューションです。Change Applier により、変更が SaveItemChange (マネージ コードの場合) メソッドまたは ISynchronousNotifyingChangeApplierTarget::SaveChange (アンマネージ コードの場合) メソッドに渡されます。この変更は、競合しない変更とまったく同じように同期先レプリカに適用されます。

両方

同期先優先

同期先レプリカが常に優先されます。リモート クライアントで行われた変更を同期先レプリカに反映しないようにする場合に使用します。Change Applier は、競合する変更をバージョンのみの変更として SaveItemChange (マネージ コードの場合) メソッドまたは ISynchronousNotifyingChangeApplierTarget::SaveChange (アンマネージ コードの場合) メソッドに渡します。同期先レプリカ上のメタデータには、バージョン情報だけが適用されます。

両方

マージ

両者間で項目の情報をマージします。Change Applier は、競合する変更をマージ変更として SaveItemChange (マネージ コードの場合) メソッドまたは ISynchronousNotifyingChangeApplierTarget::SaveChange (アンマネージ コードの場合) メソッドに渡します。同期元の項目データおよび同期先の項目データがマージされ、その結果が同期先レプリカに適用されます。

項目アクションのみ

ログ

競合を後で処理する目的でログに記録します。変更は適用されません。Change Applier により、競合する変更が SaveConflict (マネージ コードの場合) メソッドまたは ISynchronousNotifyingChangeApplierTarget::SaveConflict (アンマネージ コードの場合) メソッドに渡されます。

項目アクションのみ

保留

競合を無視します。変更は適用されません。Change Applier は、競合する変更を同期先プロバイダに渡しません。

項目アクションのみ

保存された競合

競合がログに記録された場合、SaveItemChange (マネージ コードの場合) メソッドまたは SaveChange (アンマネージ コードの場合) メソッドではなく、SaveConflict (マネージ コードの場合) メソッドまたは SaveConflict (アンマネージ コードの場合) メソッドが呼び出されます。この場合、プロバイダは、競合のナレッジ、競合する変更、および競合データを保存する必要があります。その後、アプリケーションが、これらの競合を競合ログから列挙し、解決を図ります。この種の競合解決は常にローカルの変更である点に注意してください。したがって、競合を解決するアプリケーションは、その解決処理をローカルの変更として適用し、ティック数を更新して、競合のナレッジをローカルのナレッジに追加する必要があります。

さらに、保存された競合の解決を図るアプリケーションでは、期限切れの競合も処理する必要があります。特に、プロバイダは、新しい競合をログに記録する際、ログに記録しようとしている競合が、その項目について以前ログに記録された競合よりも優先されるように、ナレッジと照らし合わせてチェックする必要があります。さらに、期限切れの競合は、ログからクリーンアップする必要があります。期限切れの競合は、プロバイダに代わり、アプリケーション側で非同期的にクリーンアップできます。この場合、アプリケーションでは、解決を試みる前に、競合が期限切れになっていないことを確認する必要があります。

変更単位を使用した競合の回避

サブ項目の変更を変更単位を使って表すことにより、競合の数を減らすことができます。変更単位を使用した場合、項目全体のバージョンではなく、変更単位のバージョンが追跡されます。したがって、同じ項目に対する変更でも、変更単位が異なれば、競合することはありません。詳細については、「変更単位の同期」を参照してください。

参照

リファレンス

ISyncKnowledge インターフェイス
ISyncProvider インターフェイス
IKnowledgeSyncProvider インターフェイス
IKnowledgeSyncProvider::ProcessChangeBatch
ISynchronousNotifyingChangeApplierTarget インターフェイス
IAsynchronousNotifyingChangeApplierTarget インターフェイス
ISyncCallback::OnConflict
CONFLICT_RESOLUTION_POLICY 列挙体
SYNC_RESOLVE_ACTION 列挙体
SyncKnowledge
KnowledgeSyncProvider
INotifyingChangeApplierTarget
ItemConflicting
ConflictResolutionPolicy
ConflictResolutionAction

概念

同期プロバイダ
変更の適用
同期ナレッジについて