Sync Guru Sync Guru
 
spacer
 
       
    Home
    Projects
    Articles
    Links
    About
 
   5555
  

  spacer

spacer
 
Synchronization Services for ADO.NET
   

 

Demo IV: Offline Application - Conflict Handling
 
It is about time for our offline application to deal with sync conflicts. Conflicts are fact of life in lazy synchronization environments. It is likely that your application users don’t want to deal with conflicts. Therefore you are encouraged to architect your solution in such a way that would make conflicts rare. However, your application is not complete without conflict handling logic. Before I go into more details, let’s define what conflict is:

“A row is said to be in conflict if it was changed on two or more nodes between synchronization requests”

In two node environment, client could make a change to a row R while offline, at the same time a change is made at the server to R. When both ends sync, a conflict is detected. In n-node environment, a conflict could happen by independent changes to R on two or more clients.


Conflict Types

The sync framework detects four types of conflicts:

  • ClientInsertServerInsert also known as PK Collision; occurs when both client and server insert a row with same PK
  • ClientUpdateServerUpdate the most common conflict; occurs when client and server make changes to the same row independently
  • ClientUpdateServerDelete occurs when the client updates a row and the server independently deletes the same row
  • ClientDeleteServerUpdate occurs when the client deletes a row and the server independently updates the same row

Note: The use of “Server” term in the conflict type names above does not necessarily mean that the changes were authored on the server. In fact, the server could be a passive node that just collects and distributes changes. However, from the synchronizing client point of view, the change appears to have happened on the server thus the naming.

To allow you to generate these conflicts without a lot of hassle, I added a button for each conflict type in the main form as show in the snapshot above.



Conflict Detection and Resolution

 

The sync framework fires ApplyChangeFailedEvent from both client and server sync providers when it detects a conflict. In this demo application, I registered to receive conflict events from both client and server providers. Each conflict is then presented to the user with possible conflict resolution options:

  1. Ignore the conflict and continue
  2. Retry applying the row, without changing to the datarow the retry will fail causing the event to be raised again. The demo does not allow you to edit the datarow though.
  3. Retry with Force Write has a built in support in the ClientSyncProvider, on the server side, you need to add support in your sync adapter commands and the demo show an example for update-update conflict.
  4. Abort the Sync by throwing an exception; all changes will be rolled back and re-synced in the next sync session.

To implement 'force write' functionality for the update-update conflict, I changed the update stored procedure from the previous demo to the following:

create procedure dbo.sp_orders_applyupdate (   
    @sync_last_received_anchor binary(8) ,
    @sync_client_id_hash int ,
    @sync_force_write int,
    @sync_rowcount int out,
    @order_id int,
    @order_date datetime = NULL )       
as         
    update [orders]
        set [order_date] = @order_date,
            [update_originator_id] = @sync_client_id_hash
        where (update_timestamp <= @sync_last_received_anchor or update_originator_id = 
               @sync_client_id_hash) and [order_id] = @order_id
    set @sync_rowcount = @@rowcount     

    -- force write resolution option
    if @sync_rowcount = 0 and @sync_force_write = 1
    begin
        update [orders]
        set [order_date] = @order_date,
            [update_originator_id] = @sync_client_id_hash    
        where [order_id] = @order_id
        set @sync_rowcount = @@rowcount
    end  
go


SyncAdapter Conflict Commands

There are two commands that we did not explore in the previous demos:

  • SelectConflictUpdatedRowsCommand this command finds conflicting rows in the base table. The sync runtime executes this command if insert, update or delete command failed (i.e. returned 0 row count)
  • SelectConflictDeletedRowsCommand this command finds conflicting rows in the tombstone table. The sync runtime executes this command if the conflicting row was not found in the base table. This is how ClientUpdateServerDelete conflict is detected.


Writing these two command is very direct as show in the code below:

create procedure dbo.sp_orders_getupdateconflict
    @order_id int
as
    -- this command finds the conflicting row in the base table for [orders]
    select order_id, order_date from orders where order_id = @order_id
go

create procedure dbo.sp_orders_getdeleteconflict
    @order_id int
as   
    -- this command finds the conflicting row in the tombstone table for [orders]
    select order_id from orders_tombstone where order_id = @order_id
go

 

How to install OfflineAppDemo application?

  1. Fire SQL server and load demo.sql file
  2. Execute the script untill the "test sample" marker
  3. Load server_procs.sql file and execute it to install server procs
  4. Load VS solution (OfflineAppDemo-Conflicts Project) 
  5. Build the project 
  6. You are ready to go


Version 1.5 [C#]: Download Now

 


 
     
 
Revision History

     January 26, 2007 - Initial release based on CTP1
     May 16, 2007 - Minor updates for beta 1.0 release
     August 17, 2007 - Update for beta 2.0 release
     November 26, 2007 - Update for RTM
     March 20, 2008 - Fix bug reported here

Resources

     Download Synchronization Services for ADO.NET V1 RTM
     Contact me through my blog 
     Communicate feedback through the MSDN forum 
 
 
 
  
 

Copyright © 2007  -  Rafik Robeal
 All Rights Reserved