Answered Server side logic (sync fx 4)

  • 2011年10月19日 14:13
     
     

    I used SyncSvcUtilUI.exe for generating server service and wp7 client, download/upload works fine.

    1. But i want to add some logic for server - receive GUID from client (done by AddFilterParameterConfiguration) then filter data using this GUID (select data using many other calculated via GUID values).

    2. How to specify SyncDirection for tables?

すべての返信

  • 2011年10月20日 1:42
    モデレータ
     
     
  • 2011年10月20日 7:46
     
      コードあり

    Thank you for answer! I read about interceptors, but i can't understand how interceptors may help me.

    I tries:

    On client - making DefaultScopeOfflineContext without parameters.

    On server -

     public static void InitializeService(Microsoft.Synchronization.Services.ISyncServiceConfiguration config) 
    {
                _syncServiceConfiguration = config;
    
                _syncServiceConfiguration.ServerConnectionString = ConfigurationManager.ConnectionStrings["ListDbConnectionString"].ToString();
    
                _syncServiceConfiguration.SetEnableScope("DefaultScope");
                _syncServiceConfiguration.AddFilterParameterConfiguration("uid", "User", "@ID", typeof(System.Guid));
    }
    
    [SyncRequestInterceptor("DefaultScope", SyncOperations.Download)]
    public void Download_Request(SyncOperationContext context)
    {
                // Add a dummy header to the response indicating that the interceptor method was invoked.
                context.ResponseHeaders.Add("DownloadRequestInterceptorFired", "true");
    <br/>//too late?
                context.QueryString.Add("uid", "43FE8AC5-53C5-4CA8-AE9B-CFABE4E4E56F");
    }
    

    And it doesn't work. Also it's ugly way.

    I suggest that i must extend Microsoft.Synchronization.Services.SyncService<T> logic?

  • 2011年10月20日 8:26
    モデレータ
     
     

    what is it exactly that you want to achieve? are you trying to do dynamic filtering?

  • 2011年10月20日 9:22
     
     

    I have big database and want to return to client only data that related to user.

    For example:

    Tables to sync - User (GUID, SpecialId, Status), Customer (CustomerId, SpecialId), Product (ProductId, CustomerId)

    Get request from client "GUID = 43FE8AC5-53C5-4CA8-AE9B-CFABE4E4E56F", filter User table by GUID (got 1 row), return Customers filtered by SpecialId, return Product filtered by CustomerId.

     

    Probably, i can modify DataSet usages (Microsoft.Synchronization.Services.SqlProvider.SqlSyncProviderService).

     


    • 編集済み spiritt1 2011年10月20日 10:00 edit
    •  
  • 2011年10月20日 10:53
     
     
    1. But i want to add some logic for server - receive GUID from client (done by AddFilterParameterConfiguration) then filter data using this GUID (select data using many other calculated via GUID values).

    To me it reads as if you are asking for JOIN and/or dynamic WHERE filtering. We have managed to get this working by manually extending some of the generated database objects, foremost the *_selectchanges.proc.sql


    Senior Jack of all trades
  • 2011年10月20日 11:40
     
     
    Yes, i guess i can provision database (using sync service util) with this additional parameters which takes same effect as a manual modifying procedures. But where at server i can assign parameters values? SyncService snaps to values at querystring.
    • 編集済み spiritt1 2011年10月20日 11:43
    •  
  • 2011年10月20日 12:28
     
     回答済み コードあり

    Our solution is to manually edit the database objects after syncfx provisioning. Actually we only use the provisioning tools as a basis for further development work. As far as i know it is not possible to describe JOIN relations in SyncScope.config.

    Here is an example of a modifiied MyTable_selectchanges.proc.sql

    ALTER PROCEDURE [dbo].[MyTable_selectchanges]
    	@sync_min_timestamp BigInt,
    	@sync_scope_local_id Int,
    	@sync_scope_restore_count Int,
    	@sync_update_peer_key Int,
    	@DeviceId NVarChar(100)
    AS
    BEGIN
    SELECT [base].[MyTableID], [base].[SomeValue], [base].[ForeignKeyID], [side].[sync_row_is_tombstone], [side].[local_update_peer_timestamp] as sync_row_timestamp, case when ([side].[update_scope_local_id] is null or [side].[update_scope_local_id] <> @sync_scope_local_id) then COALESCE([side].[restore_timestamp], [side].[local_update_peer_timestamp]) else [side].[scope_update_peer_timestamp] end as sync_update_peer_timestamp, case when ([side].[update_scope_local_id] is null or [side].[update_scope_local_id] <> @sync_scope_local_id) then case when ([side].[local_update_peer_key] > @sync_scope_restore_count) then @sync_scope_restore_count else [side].[local_update_peer_key] end else [side].[scope_update_peer_key] end as sync_update_peer_key, case when ([side].[create_scope_local_id] is null or [side].[create_scope_local_id] <> @sync_scope_local_id) then [side].[local_create_peer_timestamp] else [side].[scope_create_peer_timestamp] end as sync_create_peer_timestamp, case when ([side].[create_scope_local_id] is null or [side].[create_scope_local_id] <> @sync_scope_local_id) then case when ([side].[local_create_peer_key] > @sync_scope_restore_count) then @sync_scope_restore_count else [side].[local_create_peer_key] end else [side].[scope_create_peer_key] end as sync_create_peer_key FROM [MyTable] [base] RIGHT JOIN [MyTable_tracking] [side] ON [base].[MyTableID] = [side].[MyTableID]
    
    LEFT JOIN [OtherTable] ON [base].[ForeignKeyID] = [OtherTable].[OtherTableID]
    
    WHERE ([side].[update_scope_local_id] IS NULL OR [side].[update_scope_local_id] <> @sync_scope_local_id OR ([side].[update_scope_local_id] = @sync_scope_local_id AND [side].[scope_update_peer_key] <> @sync_update_peer_key)) AND [side].[local_update_peer_timestamp] > @sync_min_timestamp
    	AND (
    		[side].[sync_row_is_tombstone] = 1
    		OR
    		(
    			[OtherTable].[DeviceId] = @DeviceId
    		)
    	)
    
    END



    Senior Jack of all trades
    • 回答の候補に設定 M.Bi 2011年10月20日 12:29
    • 回答としてマーク spiritt1 2011年10月20日 12:32
    •  
  • 2011年10月20日 12:30
     
     回答の候補
    2. How to specify SyncDirection for tables?

    There is no such thing in SyncFX 4 CTP.

    If you want to have "read-only" sync to the client then you can this again by manually hacking the related database objects.


    Senior Jack of all trades
    • 回答の候補に設定 M.Bi 2011年10月20日 12:30
    • 回答としてマーク spiritt1 2011年10月20日 13:25
    • 回答としてマークされていない spiritt1 2011年10月21日 8:49
    •  
  • 2011年10月21日 1:25
    モデレータ
     
     回答済み

    you can provision a scope to cover your scenario without hacking the selectchanges sp by using the IN clause in your filter clause.

    for User table:

    filtercolumn = Guid, SpecialId
    filterparameter =@guid
    filterclause = "[side].[Guid] = @guid"

    for Customer table:

    filtercolumn = CustomerId, SpecialId
    filterparameter =@guid
    filterclause = "[side].[CustomerId] IN (Select CustomerId from customer_tracking c, user_tracking u where c.SpecialId = u.SpecialId AND u.Guid=@guid)"

    for Product table:

    filtercolumn = ProductId, CustomerId
    filterparameter =@guid
    filterclause = "[side].[ProductId] IN (Select ProductId from product_tracking where CustomerId IN (Select CustomerId from customer_tracking c, user_tracking u where c.SpecialId = u.SpecialId AND u.Guid=@guid))"

    i'll post provisioning code when i get a chance later.

    as for controlling Upload or Download, i think you can alter the CacheController if you want.  by default it's doing an UploadAndDownload.

    If there are changes to upload, it will submit an Upload request, otherwise it will submit a Download request. If an Upload request is made, the Download request is submitted after the Upload request is done.

     

     

     


  • 2011年10月21日 7:40
     
     

    you can provision a scope to cover your scenario without hacking the selectchanges sp by using the IN clause in your filter clause.

    The hint to hack the selectchanges sp was given by mahjayar in an early phase of the SyncFX toolkit. See Synching Related Tables and JOIN-based filtering in v3

    I am not sure if "just" a filter in the syncscope config will satisfy his requirements because as far as i know these filters are not able to handle dynamic filtering. So when the JOIN relation changes over time the changed relation would not propagate to clients which had initially synced another state.

    as for controlling Upload or Download, i think you can alter the CacheController if you want.  by default it's doing an UploadAndDownload.

    If there are changes to upload, it will submit an Upload request, otherwise it will submit a Download request. If an Upload request is made, the Download request is submitted after the Upload request is done.

    Yes, that reads like a charming approach.

    Senior Jack of all trades
  • 2011年10月21日 8:42
    モデレータ
     
     

    i dont think a join would handle dynamic filtering either. Sync Framework (including the Toolkit) has never supported dynamic filtering/partition realignment or rows going in and out of scope.

    a row will not be selected as changed simply because it satisfies the JOIN condition (or in my sample above using the IN clause), sync framework also has to see that it has changed.

    JOIN-based filtering in Sync framework is not supported simply because the filter clause is just concatenated as an additional condition in the WHERE clause containing all the other conditions for selecting what has changed.

    but that doesnt stop you from simulating a JOIN using valid constructs in a WHERE clause such as by using the IN clause.

    as pointed out in the posts you referenced above, its hard to track the changes made to the selectchanges sp and sync framework is not aware of them either.

     

  • 2011年10月21日 8:55
     
     

    simulating a JOIN using valid constructs in a WHERE clause such as by using the IN clause.

    Indeed that is a very nice idea - when you are dealing with static relations.

    i dont think a join would handle dynamic filtering either.

    But a  JOIN in selectchanges.proc can handle dynamic relations, e.g. when an employee has changed departments or a customer has moved into another group etc. I can tell that it is working just fine in our scenario.

    Sync Framework (including the Toolkit) has never supported dynamic filtering/partition realignment or rows going in and out of scope.

    We have managed to handle dynamic filtering, again by hacking the selectchanges.proc. For this we have introduced a second tracking table. Our solution might be a bit hackish but it solves our requirements.

    as pointed out in the posts you referenced above, its hard to track the changes made to the selectchanges sp and sync framework is not aware of them either.

    You are absolutely right that these kind of hacks are quite difficult to track. So they must be handled with care. As i had explained before we are using the syncfx provisioning just as a basis for further development work. For the deployment we use a standard installer to deploy all the database object with some of them heavily hacked.

     


    Senior Jack of all trades
  • 2011年10月21日 12:32
     
     

    JuneT, M.Bi

    Thanks for fast answering!