locked
ClientDeleteServerUpdate - Let Server Win RRS feed

  • Question

  • Hi

    Two questions.

    1. Could someone give an explanation behind the design decision not to raise a conflict event on the client when the server is assigned to win. I have seen this stated but not explained in other threads.

    2. I have a situation where if the server has an update on a row and a client has a delete on it, we want the update to win.
    So we need to reestablish the deleted row on the client.

    I see the conflict detected by the server's applychangefail event handler where the action is then set to continue. On the client, the changes dataset contains the server's updated row (there is only 1 change). In the syncContext.GroupProgress I can see that the TotalChanges is set to 1 , the totalChangesApplied is set to 1 and the TotalUpdates is set to 1, the TotalChangesFailed is 0. Which suggests that the ApplyChange was successful or did not have any command return sync_row_count = 0.

    But my row has not been reinstated.

    My Client UpdateCommand is pretty typical I think.
    I issue and update if sync_force_write is zero and an insert if it is set to 1.

    When I look at the SyncAdapter for the UpdateCommand I see that sync_force_write is zero so the insert isn't executed. But I would have expected the update to fail (there is no row to update, it has been deleted afterall) returning a sync_row_count of zero, which in turn should have fired a fail event.  The sync_row_count parameter has a value of zero.

    Instead the execution completes, looking like it has applied an update but hasn't.

    I am clearly missing or overlooking something.

    Regards

    Aidan


    • Moved by Max Wang_1983 Friday, April 22, 2011 6:43 PM forum consolidation (From:SyncFx - Microsoft Sync Framework Database Providers [ReadOnly])
    Wednesday, July 30, 2008 1:56 PM

All replies

  • Are you using SQL COmpact on the client?  If so, we do raise a conflict event on the client but you must trap the OnChnagesFailed event on both the server AND the client.  I suspect that you may not be trapping the change on the client as well. 

     

    On the server, your logic would look like this:

     

    Code Snippet

     private void SampleServerSyncProvider_ApplyChangeFailed(object sender, ApplyChangeFailedEventArgs e)
            {

              if (e.Conflict.ConflictType == ConflictType.ClientDeleteServerUpdate)
                {


                    e.Action = ApplyAction.Continue;

                }

    }

     

     

     

    On the client you would do the following:

     

    Code Snippet

      public SampleClientSyncProvider()
            {
               
                this.ConflictResolver.ClientDeleteServerUpdateAction = ResolveAction.ServerWins;  

     

     

     

     

    Note that I pulled these samples from the following location:

     

    http://msdn.microsoft.com/en-us/library/bb725997(SQL.100).aspx

     

     

    Regards,

     

    Sean Kelley

    Program Manager

    Microsoft

    Friday, August 1, 2008 5:21 PM
    Moderator
  • In answer to number 1, the reason you do not see a conflict on the client is because synchronization is a 2-step process: first the client uploads changes to the server and the client's changes are applied to the server, then the client downloads changes from the server and the server's changes are applied to the client.

     

    So let's say you have an update-update conflict between the server and the client.  The client will upload its update to the server.  The server will attempt to apply the update but detect the conflict.  The conflict will be resolved by the server and since it has been resolved, it does not need to be raised again by the client.  What happens during the download of changes from the server to the client depends on the conflict resolution action.  If the server wins, then the server needs to send its winning row to the client.  If the client row was chosen for conflict resolution, the row does not need to be sent back to the client.

     

    In answer to number 2, are you using the SQL Express client provider?  If so, could you provide more info on your InsertCommand and UpdateCommand?

     

    Thanks-

    Friday, August 1, 2008 7:27 PM
  • Hi Sean,

    I am using your sqlserver express as client example as a guide to create a SQLite based client provider.

    I have since got a working solution.

    As I am using a server provider I wasn't providing the 2 required conflict statements so I wasn't giving the 'client' provider the information it required and it looked like there were no conflicts.  On the client the conflict was being detected as a clientdeleteserverupdate (due I think to the server as a client perspective) so in the appliedfailed handler I switched the conflict back to clientdeleteServerUpdate and the action to forcerewrite. Now things seem to be on course, I have confirmed that I can detect conflicts and have either the server or client win. I still need to write up a substantial test suite (tomorrow's task) but I am confident that I have got to terms with the main issues.

    I must thank you for the sqlexpress as client example, it really give me the basic foundation to get started. I must admit that I needed Reflector in order to get to the bottom of some behaviour especially what happens when a ClientDeleteServerUpdate is being handled.



    Regards

    Aidan
    Sunday, August 3, 2008 10:09 PM
  • Hi Phil,

    Thanks for your reply, as I mentioned in my reply to Sean, I did manage (via Reflector) to get an understanding of what I wasn't doing, namely not supplying the conflict statements and then not catching a clientupdateserverdelete conflict.

    I did get this in your explanation, namely if the client was chosen for conflict resolution, the row does not need to be sent back to the client, I hadn't visualised that.

    Regards

    Aidan




    Sunday, August 3, 2008 10:38 PM