locked
How to detect if the client has data which has not been synchronized yet? RRS feed

  • Question

  • I'm using Sync Framework 2.1 and SQL Compact 3.5 SP2 on my client. The server is SQL Azure.

    I tried using the GetChanges method, but I could not get it working.

    I've found the following to work, but there must be a better way?

    public long ToLong(object Value)
    {
     if (Value == null)
      return 0;
     if (Information.IsDBNull(Value))
      return 0;
     return Convert.ToInt64(Value);
    }

    public bool HasNewData(ref string Message)
    {
     long resultBSN = 0;
     long resultScopeBSN = 0;
     string syncScopeName = "Group1";
     bool Result = false;
     try {
      using (SqlCeConnection CnnCE = new SqlCeConnection(pConnectionStringSQLCE)) {
       CnnCE.Open();
       SqlCeSyncScopeProvisioning SqlCEPro = new SqlCeSyncScopeProvisioning(CnnCE);
       if (SqlCEPro.ScopeExists(syncScopeName)) {
        DbSyncScopeDescription GroupScopeDesc = default(DbSyncScopeDescription);
        GroupScopeDesc = SqlCeSyncDescriptionBuilder.GetDescriptionForScope(syncScopeName, CnnCE);
        using (SqlCeCommand cmd = new SqlCeCommand()) {
         cmd.Connection = CnnCE;
         cmd.CommandText = string.Format("select scope_tomb_mark from scope_info WHERE Sync_scope_name='{0}'", syncScopeName);
         resultScopeBSN = ToLong(cmd.ExecuteScalar());
         foreach (object table_loopVariable in GruppeScopeDesc.Tables) {
          table = table_loopVariable;
          cmd.CommandText = string.Format("Select max(__sysChangeTxBsn) FROM [{0}]", table.UnquotedLocalName);
          resultBSN = ToLong(cmd.ExecuteScalar());
          if (resultBSN > resultScopeBSN) {
           Result = true;
           break; 
          }
         }

        }
       }
      }
      return Result;
     } catch (Exception ex) {
      Message = ex.Message.ToString();
      return true;
     }
    }

     

    Thanks,

    Kay

    Thursday, April 14, 2011 5:53 PM

Answers

  • it seems there is a mix of the providers here. based on your description above, you are using the peer provider doing the sync. the code you used to detech changes is incorrect as it used the sqlceclientsyncprovider.

    Dim instance As SqlCeClientSyncProvider = New SqlCeClientSyncProvider

    the post I shared out is for the SqlCeclientprovider as well so it wont work here with the peer provider.

    I think you might have a few options to achieve your goal:

    1. as previous post suggested, you can all sync, the juse the ChangesSelected on the local provider to determine if the sync will contine or not, based on if there is any changes enumerated

    2.still call the GetChangeBatch() at the local provider, you will need to write some code that does the simialr things internally as in #1. for details on how to call the GetChangeBatch(), pleae refer to this BOL section: http://msdn.microsoft.com/en-us/library/dd918908.aspx

    3. add application logic to detect changes on the tables ( I assume your app controls the data change as well as this is with SqlCe Database and likely the only access is from local machine.

    I would recommend #1 for this case as it is the most simple and straitfoward one.

    Hope this helps.

    thanks

    yunwen


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Monday, April 25, 2011 6:29 PM

All replies

  • simulate an upload sync, then on ChangesSelected or SyncProgress event, abort the sync?
    Friday, April 15, 2011 11:01 AM
  • Maybe my approach is correct?

    I would like to have it confirmed, that it is a correct way to get this information, otherwise I must contine my struggle to find the correct way.

    The reason for checking is that I have lots of clients using GPRS and generating traffic to Azure, which both have a cost.

    The clients are only uploading data, so there is no reasonto make a sync unless it is required. Otherwise I need to sync every 3 minute, which is 800 times each day. If I could reduce this to 10-20 times it would be nice.

    Kay

    Friday, April 15, 2011 8:22 PM
  • What you are proposing here is bit hackish - you are relying on tombstone mark which would get updated only if there were any deletes.

    I think using GetChanges method would be the better way to proceed.

    What problem did you face in GetChanges - can you post your code ?

     

    Other option is what JuneT suggested, start a sync and abort in ChangesSelected. This does not start any transfer so your GPRS bandwidth shouldn't be used .

    Tuesday, April 19, 2011 5:47 PM
  • Thanks Sameer,

    The best option is to get the getchanges working. My method is just a hack as you described it. The mark get updated in every sync though, even if there are no deletes.

     

    I receive this error:

    Column or constraint could not be dropped because it is referenced by a dependent view or constraint. [ __sysChangeTxBsn ]

      

    Here is my code:

     

     

    Dim instance As SqlCeClientSyncProvider = New SqlCeClientSyncProvider

    (pConnectionStringSQLCE)

     

     

    Dim tableName As String =

    "Log"

     

     

    Dim returnValue As

    SyncContext

    returnValue = instance.GetChanges(tableName)

     

     

     

      

    This table is a part of my SqlCeSyncScope which includes more than one table. 

    Wednesday, April 20, 2011 11:35 PM
  • Aan you provide the call stack and the trace of this ? is the DB ( and the table ) sync-ed to the server yet ? alternatively, you can use the info in this post to achieve your goal

    thanks

    Yunwen


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, April 21, 2011 8:05 PM
  • The DB and the table has already been sync-ed. The db has 5 scopes and 30 tables. This table belongs to the first scope which has 6 tables. I also tried a different scope which only have 1 table, but I receive the same error when calling the getchanges method.

    I've already tried the other post, without success. I'm using Sync Framework 2.1 and SqlCe 3.5 SP2. My server is SQL Azure. I think the post uses an older version of Sync Framework or an older version of SqlCe. I'm not on a device, I'm on Win7.

    I will post the call stack and a trace when I get back to my office.

    Thanks for helping me find a solution to this problem.

    Kay

    Friday, April 22, 2011 3:50 PM
  • it seems there is a mix of the providers here. based on your description above, you are using the peer provider doing the sync. the code you used to detech changes is incorrect as it used the sqlceclientsyncprovider.

    Dim instance As SqlCeClientSyncProvider = New SqlCeClientSyncProvider

    the post I shared out is for the SqlCeclientprovider as well so it wont work here with the peer provider.

    I think you might have a few options to achieve your goal:

    1. as previous post suggested, you can all sync, the juse the ChangesSelected on the local provider to determine if the sync will contine or not, based on if there is any changes enumerated

    2.still call the GetChangeBatch() at the local provider, you will need to write some code that does the simialr things internally as in #1. for details on how to call the GetChangeBatch(), pleae refer to this BOL section: http://msdn.microsoft.com/en-us/library/dd918908.aspx

    3. add application logic to detect changes on the tables ( I assume your app controls the data change as well as this is with SqlCe Database and likely the only access is from local machine.

    I would recommend #1 for this case as it is the most simple and straitfoward one.

    Hope this helps.

    thanks

    yunwen


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Monday, April 25, 2011 6:29 PM