2 ธันวาคม 2552 22:13Hi,
I'm working on handling ClientUpdateServerUpdate conflict on the client side of a synchronization using WCF between mobile device (WindowsCE on SD card) and server SqlExpress 2008.
Based on the documentation in MSDN as follows,
"Obtain the dataset of changes that is being synchronized by using the Context property. The rows exposed by the Conflict property are copies; therefore, overwriting them does not change the rows that are applied. Use the dataset exposed by the Context property to develop custom resolution schemes if the application requires them."
I want to overwrite a row in the context.DataSet.Table.Row with either the server or client conflict row, then apply a RetryWithForceWrite.
The server and client conflict rows are populated, however, the ApplyChangesFailedEventArgs' Context.DataSet is null, so I don't know how to modify the actual row that will be applied to the table.
Am I missing or misunderstanding something?
- ย้ายโดย Hengzhe Li 21 เมษายน 2554 7:44 (From:SyncFx - Microsoft Sync Framework Database Providers [ReadOnly])
5 ธันวาคม 2552 4:13เจ้าของYou need to use the SyncConflict class to achieve what you are trying to do.
Look at the member of SyncConflict calss:
Gets or sets the DataTable object that contains the conflicting rows from the client database.
Gets or sets the ConflictType enumeration value that represents the type of synchronization conflict.
Gets or sets the error message if ConflictType is set to ErrorsOccurred.
Gets or sets the DataTable object that contains the conflicting rows from the server database.
Gets or sets the SyncStage enumeration value that represents the synchronization stage during which the conflict occurred.
This posting is provided AS IS with no warranties, and confers no rights
7 ธันวาคม 2552 15:51
Thanks for the reply Mahesh.
I am using the SyncConfict class returned by the ApplyChangeFailedEventArgs. I'm comparing the columns in the conflicting rows returned in the ClientChange and ServerChange tables. Depending on the values, I may want to overwrite columns in the incoming server change row, then force a write.
Per the MSDN documentation in How to: Handle Data Conflicts and Errors (http://msdn.microsoft.com/en-us/library/bb725997.aspx) cited above, I can't use the tables exposed in the ClientChange and ServerChange to do this, as they are copies of the changes, but must use the dataset exposed by the Context property of the ApplyChangeFailedEventArgs. This is where the problem lies, as the dataset is null, though the documentation indicates it should contain all server changes (including those not in conflict). If the documentation (or my interpretation) is wrong , and I can make changes in the Conflict.ServerChage table, that will be fine.
I'll do some experimenting to see if that's the case.
7 ธันวาคม 2552 17:36Changes to the values in the ServerTable exposed in the Conflict property of the ApplyChangeFailedEventArgs are not reflected in the what's written to the client.
8 ธันวาคม 2552 1:55ผู้ตอบYes, You need to use the Context property to persist the change.
Is it possible you can handle the conflict on the SQL Express side or use a non-WCF scenario to check whether the similar situation works?
I am wondering whether the problem is related to the WCF implementation ...
8 ธันวาคม 2552 17:56Hi Jin,
I'm not sure that it's the WCF implementation;
I've verified on the server WCF service that the GetChanges method is returning a SyncContext with the DataSet, and the client's service proxy GetChanges method has that valid DataSet in the response.GetChangesResult. I can also see it in the svclog trace file.
And - when there's no conflict, changes are made on the client, so looks like the data is there.
It's just that the SyncContext object from GetChanges doesn't seem to get into the ApplyChangeFailedEventArgs SyncContext object, and I don't know how to debug that.
8 ธันวาคม 2552 21:29ผู้ตอบCan you try a few scenarios so we can get more information?
- If you just use RetryWithForceWrite, will the conflict be resolved correctly on the client side even if the Dataset is null?
- Try to sync from client to server to resolve the conflict on the server and check whether ApplyChangesFailedEventArgs.Context.DataSet is still null while the .Conflict.LocalChange & RemoteChange has valid values.
- I guess you are using SQL Ce on the WinCE side.
Can you move your client side CEProvider to same desktop as the SQL Express server, essentially 2-tier sync, will the problem still happen?
8 ธันวาคม 2552 22:48
If I skip trying to analyze the conflict and go straight to setting the action to RetryWithForceWrite, the conflict is resolved with "server wins" and the client is updated with the server changes.
I don't think I mentioned it before (and don't know if it matters), but this is a DownloadOnly scenario, not a BiDirectional.
UploadOnly sync with conflict - the ApplyChangeFailedEventArgs context.Dataset on the server is not null.
I'll add another message here when I try the last scenario.
9 ธันวาคม 2552 22:55ผู้ตอบ
My assertion that "use the Context property to persist the change" was WRONG. My assumption was that you were using Sync Framework V2 (ADO.NET Sync services V3) DbSyncProvider or SqlSyncProvider collabration model.
After discussion with our colleagues,
In the case of offline scenario with DbServerSyncProvider & SqlCeClientSyncProvider, for your scenario.
In the ApplyChangeFailed event handler, ApplyChangeFailedEventArgs has the Conflict property for viewing conflict rows, the Context.Dataset property should not be used to change the rows in custom way.
To make a custom resolution on the SQLCe side (DownloadOnly situation), you can use the Connection & Transaction on the ApplyChangeFailedEventArgs to apply the changes to the SQLCe with a "Continue" conflict resolution option.
- ทำเครื่องหมายเป็นคำตอบโดย cbp 10 ธันวาคม 2552 19:52
9 ธันวาคม 2552 23:15So, I need to generate a SQL command that makes the changes to the local database, execute the query, then set the action to .Continue, is that right?
I'll give that a try tomorrow.
Thanks for the info! It sure seems like the MSDN documentation implies that the same logic works for both server and client...
10 ธันวาคม 2552 20:01Jin,
Looks like that did the trick. In my testing I generated a sqlCeCommand in the ApplyChangeFailed event which overwrote only selected columns in the client table, executed it, set the action to Continue. The changes appeared correctly in the client table.
Thanks for your help!