Handling Data Conflicts in the Microsoft Sync Framework
IntroductionData conflicts are inevitable in any application or framework that synchronizes data from multiple data sources that are influenced by numerous people. The Microsoft Sync Framework (MSF) is no exception. MSF does, however, have built-in features to help developers deal with the most common conflict scenarios. Let's look at how MSF Services for ADO.NET v1.0 helps to lighten the burden of conflict resolution on the developer.
If you are new to the Microsoft Synchronization Framework and need to get up to speed before jumping into conflict resolution, you can check out this article and this blog post to get started. We assume a general knowledge of the MSF framework in the following examples.
First, we must understand what a data conflict is and how it is generated. Listing 1.1 shows the most common data conflict that occurs when two sources make updates to a single row of data. For example, imagine a situation where you have two clients (Client A and Client B) making updates to a local data cache that is then synchronized to a server. Client A and Client B both synchronize with the server, receiving the same copy of the information in Table X. Client A updates a phone number in Row #17 of Table X and syncs with the server. Meanwhile, Client B updates an email address in Row #17. When Client B then syncs with the server, a data conflict occurs as the server tries to decide which copy of the data (Client A's row or Client B's row) should "win" and be written to the master copy in the server. Decisions like this can be made in the application's business logic. MSF provides a couple of different ways to define this logic.
Listing 1.1 Common synchronization conflict example
Conflict Types and Apply ActionsThe MSF defines five distinct conflict types, which are defined as the ConflictType enumerations.
- ClientInsertServerInsert - A new row is created with the same primary key.
- ClientUpdateServerUpdate - The same row is updated. This is the most common conflict, as shown in Listing 1.1.
- ClientUpdateServerDelete - A row is updated on the client but has been deleted on the server.
- ClientDeleteServerUpdate - A row is deleted on the client but has been updated on the server.
- ErrorsOccurred - The "catch all" that is used when any error (not covered by the above cases) prevents a row from being inserted, updated or deleted.
Our example in Listing 1.1 might have you thinking that data conflicts will only occur when the synchronization scheme is bi-directional. However, this is not the case. Imagine an upload-only situation where the client doesn't care about updates made on the server and just wants to feed its new information to the server. The client will create a row of data and sync with the client. At some point, some pesky user mucking around with the server data decides this row is no longer needed and deletes it. In the meantime, the client makes a change to that row and tries to sync with the server to update the server copy. This will still cause a conflict because the row that the client updated has been deleted. In this situation, one conflict resolution scheme might change the update to an insert to resolve the conflict.
In addition to the conflict types described above, MSF defines three built-in actions for resolving a conflict, which are defined in the ApplyAction enumeration.
- Continue - This is the default action, which allows you to continue to the next conflict in the list.
- RetryApplyingRow - This will retry to apply the row's changes. This will fail again unless you change the data in some way (usually with a custom conflict resolution scheme in code that matches the business logic for handling conflicts).
- RetryWithForceWrite - This will force the application of the row changes (overwriting any conflicting data).
We will take a look at the effect of these actions on some of the conflict types in the following sections.
Page 1 of 4