The Local Database Cache item in Visual Studio by default generates code for Snapshot or Incremental downloads only.
To change the sync to upload only, it is not enough that the SyncDirection is set to UploadOnly. When you simply set SyncDirection=SynDirection.UploadOnly, you will run into an issue where subsequent updates on rows in the client side are not uploaded to the server.
This is because by default, the designer generated code compares timestamp column (or whatever column you choose for comparing updates) to the last_received_anchor. If you inspect the generated UpdateCommand, the update statement Where clause looks similar to this:
WHERE ([Id] = @Id) AND (@sync_force_write = 1 OR ([TimeStamp] <= @sync_last_received_anchor)
The condition: ([TimeStamp] <= @sync_last_received_anchor) is there to check that the server row being updated by the update coming from the client has not been updated in the server side since the last synchronization. A client update on a row that has been updated also in the server is treated as a conflict.
The last_received_anchor is a timestamp anchor stored on the client side to mark the high watermark when changes were last retrieved from the server. This anchor is then used as the low watermark on the next sync.
i.e., WHERE ([TimeStamp] > @sync_last_received_anchor AND [TimeStamp] <= @sync_new_received_anchor)
The last received anchor is first/last set by the designer when you configure the sync. By configuring the sync direction to UploadOnly, no new anchor value is downloaded and saved on the last_received_anchor on the client side since Sync framework won’t bother to retrieve and store an anchor value from the server side that marks the high watermark timestamp on the server during the sync.
Here’s how to reproduce the scenario:
1. Assuming two rows in the server with timestamp 0x0000000000000FA1 and 0x0000000000000FA5
2. Use Local Database Cache Designer, using timestamp as update column, new and incremental updates (there is no option for bidirectional or upload only in the designer)
3. Rows get downloaded to the SDF, last received anchor is set to 0x0000000000000FA5
4. Change sync direction to UploadOnly
5. Do an insert on the SDF and sync, SQL Profiler shows last received anchor as 0x0000000000000FA5, this works since inserts on server doesn’t check for timestamp
6. Newly inserted/uploaded row in server gets a timestamp of 0x0000000000000FA6
7. Update the row on client again then sync, SQL profiler shows last received anchor still as 0x0000000000000FA5 (we only upload so last received never changes), however timestamp of the same row which was previously uploaded and inserted to server in step 5/6 is 0x0000000000000FA6.
8. Where condition is 0x0000000000000FA6 <= 0x0000000000000FA5, so it fails and no update happens.
To work around this issue, you can remove the condition ([TimeStamp] <= @sync_last_received_anchor). But this will result to the client overwriting the server changes with its own changes.
A more elegant solution is to simply configure the sync direction to BiDirectional but configuring sync as well not to select and download changes from the server side. This would allow sync to retrieve a new anchor value for the last_received_anchor without retrieving any rows from the server.
Here’s how to the code looks like:
I hope this helps.