locked
How to remove the old data when synchronization by Microsoft SyncFramework on Device? RRS feed

  • Question

  • Dear all,

    I have an application on Device to synchronize between PC <--> Device.

    I'm using the MS SyncFramework 2.0. But I don't know how to remove old data on device after it's already updated on server by another device.

    EX:

    Request01 has 2 statuses: Created and Completed

    My business: Only synchronize to get data from Server to Device with created status.

    I have 2 device: A, B. They have already synchronized the first time & the Request01 was downloaded to them with Created status.

    Then device A completed that request. And sync to upload back to server. Request01 was completed. But Request01 on Device B till Created.

    How to know that request has been completed on server to remove it on device B.

    Regards,

    DanhPC

    • Moved by edhickey Tuesday, July 20, 2010 3:59 PM (From:.NET 3.0/3.5 Windows Workflow Foundation)
    Tuesday, July 20, 2010 8:57 AM

Answers

  • here's a quick look at how to go about it, this doesnt include Dong's suggestion of clearing out the other columns other than the PK to minimize the payload.

    void LocalDataCache1ServerSyncProvider_ChangesSelected(object sender, Microsoft.Synchronization.Data.ChangesSelectedEventArgs e)
      {
       //let's check if we're synching the table we're interested
       if (e.Context.DataSet.Tables.Contains("WorkOrders"))
       {
        var dataTable = e.Context.DataSet.Tables["WorkOrders"];
        for (int j = 0; j < dataTable.Rows.Count; j++)
        {
         DataRow row = dataTable.Rows[j];
    
         // we're only interested in updates
         if (row.RowState == DataRowState.Modified)
         {
          // check if the status is Completed
          if (row["Status"].ToString() == "Completed")
          {
           // let's delete the row so it gets applied as a delete instead of applying it as an update
           dataTable.Rows[j].Delete();
          }
         }
        }
       }
    
      }
    
    Monday, September 6, 2010 2:10 PM

All replies

  • Hi danhpc,

    Sync framework does not generate tombstones when a row moves out of the the filter. In this case Reques01 moved out of the filter because its status changed to completed but this will not be passed as a tombstone to Device B because there is a filter to enumerate only created rows.

    Tuesday, July 20, 2010 9:13 PM
  • Dear Geneshan,

    Thank for your answer. I know that only get created status. But I don't know which function in Sync Framework can check any changes in database at that time?

    If I change my business, allow sync both status created & completed. May be, performance won't good.

    If I remove that after sync --> my business may be wrong when I don't know any changes on server.

    Do you have any solutions? Could you please share to me your solution?

    Regards,

    DanhPC

    Wednesday, July 21, 2010 3:36 AM
  • hi danhpc,

    I would recommend that you try to sync both created and completed status and measure if the performance is acceptable. Also how many records will be sync'd on an average?

    Thursday, July 22, 2010 5:31 PM
  • Dear Ganeshan,

    I have about 100 requests/day --> 36500 requests/year for 1 table. I have 5 tables like that & my database has about 25 tables. Moreover, I sync between PC <--> Device.

    If I sync both created & completed status, data is downloaded to Device is very big. Performance won't good & memory to store data on device is limitted.

    Sync with all status is not good in my case, right?

    Regards,

    DanhPC

    Friday, July 23, 2010 3:07 AM
  • Hi danhpc,

    Unfortunately there is not much we can do about the space consumption on the client for this scenario. You will only be able to delete records from the device if you get a tombstone from the server. And in your case, it does not look like you want to delete rows from the server.

    However, we are working on Sync Framework 3.0 which can enable this scenario. The current CTP of Sync Framework 3.0 supports building sync applications with SQL Server or SQL Azure databases on the server side. If this is something you are interested in then, please check out the announcements at http://social.msdn.microsoft.com/Forums/en-US/synclab/threads?lc=1033&prof=required for more information about how to participate.

    Tuesday, July 27, 2010 8:57 PM
  • Hi Ganeshan,

     

    I'd like to delete that rows at client (not from server). In my case, that data is rubbish.

    I think in Sync Framework 3.0. It should have this scenario. Because on mobile everything always less than PC. It's very difficult to do.

    Totally, In my case. Don't have the way to do that on Sync Framework 2.0 with the reason as I told, right?

     

    Thanks & Regards,

    DanhPC

    Sunday, August 1, 2010 12:19 PM
  • You can use the SelectIncrementalDeleteCommand to select what needs to be deleted on the client. Even though its not deleted on the server you can say select * from table where status <> Created ... this should delete the record on the client.
    Friday, August 6, 2010 12:28 PM
  • be careful with running a delete operation on the client directly as the deletes will update the change metadata and the delete operations will be enumerated as changes for upload and consequently may be applied on the server.

    another approach will be to define a new, download only sync group with the same table. This time specify a "Completed" filter. You are then able to enumerate and download the changes.

    If you're using WCF, you can simply apply the deletes on the client side. Just make sure that on upload, you intercept the change dataset in the SyncContext and remove the deleted rows from the change dataset so that only updates are uploaded.

    Saturday, August 7, 2010 10:07 PM
  • Hi JuneT,

    I'm now running into a similar situation.

    Could you elaborate on how this should work.  I can see the logic except for the bit with the new download group - how do you intercept the changes before they are inserted into the table?  The other issue is that surely the completed filter would pull back all of the records?

    Failing that would resetting the anchor on this table for every sync cause the changed records to be uploaded and the irrelevant records to be removed.  Not something to do on big tables but when we are talking 100 or max of 200 records in my case it shouldn't be too much of a strain.

    Best Regards,

    Jon

    Friday, September 3, 2010 10:29 AM
  • The original poster mentioned Device synchronization so am assuming this is using the offline provider (SqlCeClientSyncProvider). The offline sync has a concept of SyncGroups which is the counterpart of Scopes for the SqlSyncProvider. the offline provider is anchor based where there is a table that keeps track of last sent and last  received anchors and you can actually set these values(SetTableSentAnchor/SentReceivedAnchor). Am also assuming this has a WCF component.

    on second thought, there might not even be a need to create a separate sync group. instead of filtering on the server for "Created" rows only, the "Completed" rows should also be downloaded.

    The "Created" rows will be flagged in the dataset as new rows for Insert, the "Completed" as Updates. In the client WCF proxy, the downloaded changes will be returned in the GetChanges operation (in WCF service side or in the client proxy) . The dataset can be intercepted there and updated so that all "Completed" rows are tagged as Deletes instead of Updates and let Sync Fx apply it.

    havent tried it though. :)

     

    Friday, September 3, 2010 2:40 PM
  • JuneT's proposal looks reasonable to me. After loading DataSet with GetChanges in PC side, you can call DataRow.Delete for all "Completed" rows to change them to deleted ones. You can also cleanup the DataRow.ItemArray for non-pk values to reduce the download size.

    Thanks,
    Dong


    This posting is provided AS IS with no warranties, and confers no rights.
    Friday, September 3, 2010 7:01 PM
  • Many thanks for the clarification Dong.  I'll have a look at this over the next couple of weeks. 

    Regards,

    Jon

    Monday, September 6, 2010 2:05 PM
  • here's a quick look at how to go about it, this doesnt include Dong's suggestion of clearing out the other columns other than the PK to minimize the payload.

    void LocalDataCache1ServerSyncProvider_ChangesSelected(object sender, Microsoft.Synchronization.Data.ChangesSelectedEventArgs e)
      {
       //let's check if we're synching the table we're interested
       if (e.Context.DataSet.Tables.Contains("WorkOrders"))
       {
        var dataTable = e.Context.DataSet.Tables["WorkOrders"];
        for (int j = 0; j < dataTable.Rows.Count; j++)
        {
         DataRow row = dataTable.Rows[j];
    
         // we're only interested in updates
         if (row.RowState == DataRowState.Modified)
         {
          // check if the status is Completed
          if (row["Status"].ToString() == "Completed")
          {
           // let's delete the row so it gets applied as a delete instead of applying it as an update
           dataTable.Rows[j].Delete();
          }
         }
        }
       }
    
      }
    
    Monday, September 6, 2010 2:10 PM
  • Hi JuneT,

    That works a treat thanks.  I still need to clear down the non PK data to speed things up but that's for next week!

    One issue that I have come across is that this works well for basic filters such as getting rid of Completed entries.  As soon as the filter would need a join type evaluation it's rather tricky.  To that end when filterin a child table I have the Completed flag saved into that table too and just populate it from an update trigger on the parent table.

    Now to get this working properly from the Client to the Server as well!

    Have a good weekend,

    Regards,

    Jon

    Friday, October 1, 2010 2:10 PM
  • Thank JuneT & DongCao,

     

    It works well. Thank you for your help.

    I have incorporated the deletion of changes at client after upload changed data to server and applied the deletion at server via WCF.

     

    Thanks & regards,

    DanhPC

    Saturday, November 20, 2010 1:06 PM
  • How would you do this when using some thing like this?

     

    // create the sync orhcestrator
                    var syncOrchestrator = new SyncOrchestrator();

              
                    // set local provider of orchestrator to a CE sync provider associated with the 
                    // All_Active_Form in the SyncCompactDB compact client database
                    var stuff = new SqlCeSyncProvider("All_Active_Device", _clientConn, "Sync");
                    syncOrchestrator.LocalProvider = new SqlCeSyncProvider("All_Active_Device", _clientConn, "Sync");
                

                    // set the remote provider of orchestrator to a server sync provider associated with
                    // the All_Active_Form in the SyncDB server database
                    syncOrchestrator.RemoteProvider = new SqlSyncProvider("All_Active_Device", _serverConn, null,"Sync");


                    // set the direction of sync session to Download 
                    syncOrchestrator.Direction = SyncDirectionOrder.Download;
    Tuesday, November 23, 2010 4:03 PM
  • string _deviceName = cbDevice.Text;
                // create the sync orhcestrator
                var syncOrchestrator = new SyncOrchestrator();

                //// set local provider of orchestrator to a CE sync provider associated with the 
                //// FilteredCandidates in the SyncCompactDB compact client database

                var localCeSyncProvider = new SqlCeSyncProvider("CandidateFor" + _deviceName, _clientConn, "Sync");
                localCeSyncProvider.ChangesSelected += new EventHandler<DbChangesSelectedEventArgs>(localCeSyncProvider_ChangesSelected);
                syncOrchestrator.LocalProvider = localCeSyncProvider;
     void localCeSyncProvider_ChangesSelected(object sender, DbChangesSelectedEventArgs e)
            {

                //What this will do is deleate the data on the server not remove this data from the client
                //let's check if we're synching the table we're interested
                if (e.Context.DataSet.Tables.Contains("Candidate"))
                {
                    var dataTable = e.Context.DataSet.Tables["Candidate"];
                    for (int j = 0; j < dataTable.Rows.Count; j++)
                    {
                        DataRow row = dataTable.Rows[j];

                        // we're only interested in updates
                        if (row.RowState == DataRowState.Modified)
                        {
                            // check if the status is Done
                            if (row["CandidateIsDone"].ToString() == "True")
                            {
                                // delete the row so it gets applied as a delete instead of applying it as an update
                                dataTable.Rows[j].Delete();
                            }
                        }
                    }
                }
            }
    So now I still have data on the Client but the Record on the server gets deleted. what I waht is the other way arounf no client date but keeps the server Data. I have tried to place the code on the RemoteProvider but that does not do anything.
    Tuesday, November 23, 2010 6:46 PM