none
Custom conflict resolution results not showing on client RRS feed

  • Question

  • I have a sync framework setup, and during normal use of the application it's going to result in both the client and the server inserting a row for the same primary key, with different columns filled out.  Rather then having the client or server win, I want to merge the data in the two rows and then use the resulting on both sides.  I've been following the guide here http://msdn.microsoft.com/en-us/library/bb725997.aspx on creating a custom conflict resolution method.  The server side works, the rows merge and upload to the server, however the merged row is not then downloaded back to the client.  I've hooked into the ApplyChangeFailed event for the ClientSyncProvider, however it never fires like the one for the ServerSyncProvider does.

    public MyServerSyncProvider() {
        string connectionString = MyServerConnectionString;
        this.InitializeConnection(connectionString);
        this.InitializeSyncAdapters();
        this.InitializeNewAnchorCommand();
        this.OnInitialized();
        this.ApplyChangeFailed += new System.EventHandler<Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs>(MyServerSyncProvider_ApplyChangeFailed);
    }

    Custom server conflict resolution method.  Columns 1 & 2 are the primary key.  It loops through each column, if the client change and server change don't match, it checks to see if the client change value is null, and if so updates the context dataset for that row/column to the server value, then forces the write.

    void MeTER2011_1ServerSyncProvider_ApplyChangeFailed(object sender, Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs e)
    {
        if (e.Conflict.ConflictType == Microsoft.Synchronization.Data.ConflictType.ClientInsertServerInsert || e.Conflict.ConflictType == Microsoft.Synchronization.Data.ConflictType.ClientUpdateServerUpdate)
        {
            for (int i = 0; i < e.Conflict.ClientChange.Columns.Count; i++)
            {
                if (e.Conflict.ClientChange.Rows[0][i] != e.Conflict.ServerChange.Rows[0][i])
                {
                    if (e.Conflict.ClientChange.Rows[0][i] == DBNull.Value)
                    {
                         for (int j = 0; j < e.Context.DataSet.Tables[0].Rows.Count; j++)
                         {
                             if (e.Context.DataSet.Tables[0].Rows[j][1].ToString() == e.Conflict.ServerChange.Rows[0][1].ToString() && e.Context.DataSet.Tables[0].Rows[j][2].ToString() == e.Conflict.ServerChange.Rows[0][2].ToString())
                                 e.Context.DataSet.Tables[0].Rows[j][i] = e.Conflict.ServerChange.Rows[0][i];
                         }
                    }
                }
            }
            e.Action = Microsoft.Synchronization.Data.ApplyAction.RetryWithForceWrite;
         }
    }
    public MyClientSyncProvider() {
       this.ConnectionString = MyClientConnectionString;
       this.ConflictResolver.ClientInsertServerInsertAction = Microsoft.Synchronization.Data.ResolveAction.FireEvent;
       this.ConflictResolver.ClientUpdateServerUpdateAction = Microsoft.Synchronization.Data.ResolveAction.FireEvent;
    
       this.ApplyChangeFailed += new EventHandler<Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs>(MyClientSyncProvider_ApplyChangeFailed);
    }

    This event never fires.

    void MyClientSyncProvider_ApplyChangeFailed(object sender, Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs e)
    {
        throw new NotImplementedException();
    }


    EDIT:

    Been working with it some more and I'm pretty sure I understand WHY it's not working, I just don't know how to fix it.  If I'm understanding it correctly, by using RetryWithForceWrite during the server sync, it's writing the updated row to the server, but it then thinks the client row is correct and doesn't need to be synced, even though it's still the original unmerged row.  I need to know how to tell the sync to write the row to the server, but still leave the client row invalid and download it back from the server.  I could probably hack it and execute a query during that conflict method to manually update the client database, but that doesn't seem right, and I'm pretty sure wouldn't give an accurate Upload/Download count in the sync results stat.

    Tuesday, February 26, 2013 1:30 PM

All replies

  • quickest workaround is to remember the PKs of the rows you merged, then on the ChangesApplied event, do a dummy update on those rows...
    Wednesday, February 27, 2013 11:05 AM
    Moderator