衝突検出付き読み取り/書き込み
このデータの同期パターンは、アプリがオフラインの間に複数のエンドユーザーが同じデータを変更する高度なシナリオで推奨されます。
- サーバーデータベースは、時間的とともに変化する可能性のあるマスターデータを保持しています。
- ローカルストレージデータベースは、マスターデータのサブセットを保持し、変更することができます。
- 同期によって、変更されたデータがローカルストレージからサーバーデータベースへ、またその逆方向に送信されます。
- サーバーでは、データが更新され、衝突のある変更は、後で解決するために記録されます。
以下は、衝突検出付き読み取り/書き込みパターンの概要です。
-
解決されていない衝突があるかどうかを確認します。衝突がある場合、クライアントは同期を中止して未解決の衝突を報告します。
-
アプリが変更したローカルストレージデータをサーバーに送り返します。
-
データベースに衝突のある変更があるかどうかをチェックします。
-
クライアントデータとの衝突の場合は、レコードを衝突リストに追加します。
-
衝突のないデータベースレコードを更新します。
-
更新されたデータベースデータおよび衝突のある変更のリストを送信します。
-
衝突を確認します。衝突がある場合、衝突を記録してローカルストレージを衝突のないレコードで更新します。衝突がない場合は、ローカルストレージのデータを削除し、サーバーから取得したデータで作成し直します。
-
ローカルストレージの最後の同期タイムスタンプを更新します。
-
該当する場合、エンドユーザーに未解決の衝突を報告します。
検出された衝突を解決する自動または手動の仕組みを実装する必要があります。たとえば、クライアント側のレコードとサーバー側のレコードを並べて表示してどちらを残すかをエンドユーザーに選択してもらうことができます。
衝突検出付き読み取り/書き込みパターンのサンプルモジュールをダウンロードします。このサンプルモジュールでは、データの同期の例として複数の企業が使用されています。以下のセクションでは、サンプルモジュールで使用されているデータモデルおよびロジックについて詳細に説明しています。
データモデル
このサンプルでは、Company
データベースエンティティとそれに対応するLocalCompany
ローカルストレージエンティティを定義します。さらに、LocalCompany
エンティティには、レコードの同期状態を追跡するための3つのメタデータアトリビュートを定義します。SyncProperties
ローカルストレージエンティティには最後の同期の日時を保持し、ConflictingCompany
ローカルストレージエンティティには衝突レコードを保持します。
- レコードが最後に更新または作成されたときにタイムスタンプを保存することにより、変更されたレコードを追跡します。
- 削除されたレコードを追跡します。
- レコードの同期状態を追跡するメタデータアトリビュートです。
- 衝突レコードを保持します。
- 最後の同期のタイムスタンプ。このタイムスタンプは、クライアントとサーバーと間の時刻の相違による問題を避けるために、サーバー側で設定されることにご注意ください。
アプリケーションのロジックは、以下に示すように、ローカルエンティティのIsFromServer
、IsModified
およびIsActive
メタデータアトリビュートを更新する必要があります。
IsFromServer
: Trueの場合、レコードがサーバーに存在しています。IsModified
: Trueの場合、レコードがローカルで変更されています。IsActive
: Falseの場合、レコードはローカルで削除されていますが、サーバーからは削除されていない可能性があります。
OfflineDataSyncロジック
以下は、OfflineDataSync
クライアントアクションのロジックの説明です。
-
ConflictingCompany
のレコード数を取得し、前回の同期以降の未解決の衝突がある場合は例外をトリガーします。 -
最後の同期のタイムスタンプを取得します。
-
ローカルで追加・修正・削除されたCompanyレコードのリストを取得します。
追加されたレコードを取得するAggregateでは、以下のフィルタを使用します。LocalCompany.IsFromServer = False and LocalCompany.IsActive = True
変更されたレコードを取得するAggregateでは、以下のフィルタを使用します。
LocalCompany.IsModified = True and LocalCompany.IsFromServer = True and LocalCompany.IsActive = True
削除されたレコードを取得するAggregateでは、以下のフィルタを使用します。
LocalCompany.IsActive = False and LocalCompany.IsFromServer = True
-
ローカルで追加・更新・削除されたCompanyレコードのリストを入力として、
ServerDataSync
サーバーアクションを呼び出します。サーバーは、データベースのデータを更新し、更新されたCompanyレコードのリスト、衝突のあるCompanyレコードのリストおよび衝突のあるCompanyレコードのIDリストを返します。 -
サーバーから返された衝突のあるCompanyレコードに対応する元のCompanyレコードのリストを取得します。
-
ローカルストレージのすべてのCompanyレコードを削除します。
-
ローカルストレージのCompanyレコードを作成し直し、サーバーから返された衝突のあるレコードを
ConflictingCompany
エンティティに追加します。 -
サーバーから返されたこの同期のタイムスタンプで
SyncProperties.LastSync
エンティティアトリビュートを更新します。
ServerDataSyncロジック
以下は、ServerDataSync
サーバーアクションのロジックの説明です。
-
この同期のタイムスタンプを出力パラメータに割り当てます。
-
ローカルで追加されたCompanyレコードのリストを繰り返し、データベースに、ModifiedOnアトリビュートを現在のタイムスタンプで設定したレコードを作成します。
-
ローカルで変更されたCompanyレコードのリストを繰り返します。リスト内の各レコードに対して、データベースの対応するCompanyレコードを取得し、それが最後の同期以降に変更されたかどうかを確認します。
- 変更されていない場合、データベースのそのCompanyレコードを更新します。
- 変更されている場合、そのCompanyレコードを衝突のある企業のリストに追加します。
-
ローカルで削除されたCompanyレコードのリストを繰り返します。リスト内の各レコードに対して、データベースの対応するCompanyレコードを取得し、それが最後の同期以降に変更されたかどうかを確認します。
- 変更されていない場合、データベースのそのCompanyレコードを削除します。
- 変更されている場合、そのCompanyレコードを衝突のある企業のリストに追加します。
-
衝突のあるCompanyレコードが存在しない場合は、データベースからすべてのCompanyレコードを取得し、それらをクライアントに返します。
-
衝突のあるCompanyレコードが存在する場合は、データベースから衝突のないComanyレコードを取得し、衝突のあるCompanyレコードのリストとともに、それらをクライアントに返します。