How to: Configure N-Tier Synchronization
This topic shows you how to configure N-tier synchronization for Microsoft Synchronization Services for ADO.NET. The examples in this topic focus on the following Synchronization Services types:
For information about how to run sample code, see "Example Applications in the How to Topics" in Programming Common Synchronization Tasks.
In an N-tier synchronization architecture, synchronization components are spread across multiple tiers, as shown in the following diagram.

In a two-tier architecture, all components reside on the client, and the client communicates directly with the server. In an N-tier architecture, the server synchronization provider resides on the server or another tier, and communication between the tiers is handled by the ServerSyncProviderProxy object and a service, such as a Windows Communication Foundation (WCF) service. One of the strengths of Synchronization Services is the ease with which you can move code from a two-tier architecture to an N-tier architecture. If the code is factored appropriately, after you create a service and add a proxy, only a small change to synchronization agent code is required. Client and server synchronization providers do not have to be changed.
The following code examples show the main components that are involved in an N-tier architecture. Additional WCF components are required. These components are generated for you if you use Visual Studio 2008. For more information, see the Visual Studio documentation and the samples at this Microsoft Web site.
Key Parts of the API
This section provides code examples that demonstrate the similarities between two-tier and N-tier synchronization, and point out the key parts of the API to use when you are configuring N-tier synchronization. The following code example is from a class that derives from SyncAgent. For two-tier synchronization, the client provider and server provider are both referenced directly in the synchronization agent as local and remote providers.
Me.LocalProvider = New SampleClientSyncProvider() Me.RemoteProvider = New SampleServerSyncProvider()
The following code example references the client provider directly, as in the two-tier example. However, the remote provider now references a proxy instead of directly referencing the server provider. The proxy is created by passing a reference to a WCF service.
Me.LocalProvider = New SampleClientSyncProvider() Dim serviceProxy As New ServiceReference.ServiceForSyncClient() Me.RemoteProvider = New ServerSyncProviderProxy(serviceProxy)
The following code examples create client and server providers. This code is identical whether a two-tier or N-tier architecture is used.
public class SampleClientSyncProvider : SqlCeClientSyncProvider { public SampleClientSyncProvider() { //Specify a connection string for the sample client database. Utility util = new Utility(); this.ConnectionString = util.ClientConnString; } }
Public Class SampleClientSyncProvider Inherits SqlCeClientSyncProvider Public Sub New() 'Specify a connection string for the sample client database. Dim util As New Utility() Me.ConnectionString = util.ClientConnString End Sub End Class
Public Class SampleServerSyncProvider Inherits DbServerSyncProvider Public Sub New() 'Create a connection to the sample server database. Dim util As New Utility() Dim serverConn As New SqlConnection(util.ServerConnString) Me.Connection = serverConn 'Create a command to retrieve a new anchor value from 'the server. Dim selectNewAnchorCommand As New SqlCommand() Dim newAnchorVariable As String = "@" + SyncSession.SyncNewReceivedAnchor selectNewAnchorCommand.CommandText = "SELECT " + newAnchorVariable + " = min_active_rowversion() 1" selectNewAnchorCommand.Parameters.Add(newAnchorVariable, SqlDbType.Timestamp) selectNewAnchorCommand.Parameters(newAnchorVariable).Direction = ParameterDirection.Output selectNewAnchorCommand.Connection = serverConn Me.SelectNewAnchorCommand = selectNewAnchorCommand 'Create a SyncAdapter for the Customer table manually, or 'by using the SqlSyncAdapterBuilder as in the following 'code. Dim customerBuilder As New SqlSyncAdapterBuilder(serverConn) customerBuilder.TableName = "Sales.Customer" customerBuilder.TombstoneTableName = customerBuilder.TableName + "_Tombstone" customerBuilder.SyncDirection = SyncDirection.DownloadOnly customerBuilder.CreationTrackingColumn = "InsertTimestamp" customerBuilder.UpdateTrackingColumn = "UpdateTimestamp" customerBuilder.DeletionTrackingColumn = "DeleteTimestamp" Dim customerSyncAdapter As SyncAdapter = customerBuilder.ToSyncAdapter() customerSyncAdapter.TableName = "Customer" Me.SyncAdapters.Add(customerSyncAdapter) End Sub End Class
The following code example creates an interface that the service implements. The interface includes the four key methods of the server provider.
<ServiceContract()> _ Public Interface IServiceForSync <OperationContract()> _ Function ApplyChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal dataSet As DataSet, ByVal syncSession As SyncSession) As SyncContext <OperationContract()> _ Function GetChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal syncSession As SyncSession) As SyncContext <OperationContract()> _ Function GetSchema(ByVal tableNames As Collection(Of String), ByVal syncSession As SyncSession) As SyncSchema <OperationContract()> _ Function GetServerInfo(ByVal syncSession As SyncSession) As SyncServerInfo End Interface
The following code example creates a service. This service implements the interface that was created in the previous code example and references the server provider.
Public Class ServiceForSync Implements IServiceForSync Private _serverSyncProvider As SampleServerSyncProvider Public Sub New() Me._serverSyncProvider = New SampleServerSyncProvider() End Sub <System.Diagnostics.DebuggerNonUserCodeAttribute()> _ Public Overridable Function ApplyChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal dataSet As DataSet, ByVal syncSession As SyncSession) As SyncContext Return Me._serverSyncProvider.ApplyChanges(groupMetadata, dataSet, syncSession) End Function <System.Diagnostics.DebuggerNonUserCodeAttribute()> _ Public Overridable Function GetChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal syncSession As SyncSession) As SyncContext Return Me._serverSyncProvider.GetChanges(groupMetadata, syncSession) End Function <System.Diagnostics.DebuggerNonUserCodeAttribute()> _ Public Overridable Function GetSchema(ByVal tableNames As Collection(Of String), ByVal syncSession As SyncSession) As SyncSchema Return Me._serverSyncProvider.GetSchema(tableNames, syncSession) End Function <System.Diagnostics.DebuggerNonUserCodeAttribute()> _ Public Overridable Function GetServerInfo(ByVal syncSession As SyncSession) As SyncServerInfo Return Me._serverSyncProvider.GetServerInfo(syncSession) End Function End Class
Complete Code Example
For a complete code example of an N-tier synchronization application, see this Microsoft Web site.