Microsoft Sync Framework is a powerfull data .NET library provided by Microsoft which can be used to mantain synchronized two or more data sources. In this post I wish to share a sample project I developed to test Sync Framework features. In my project I had a server database (SqlServer 2008 any edition), a WinForms/WPF application used to access data from a workstation running Windows and a mobile application running on a Windows Mobile 6.1 PDA. Communication between system components is realized through WCF.

In the following figure I'll show the main components that are parts of the test system:

As you can see from the above image there are many actors in the system but using many of the most recent tecnologies like WCF, Linq, Sync Framework as well as WPF you can build a workable starting solution in half an hour.

List of all involved tecnologies and their usage:

  1. Sync Framework is used to retrieve changes made to source database and to apply correct modifications to destination database.
  2. WCF is used to communicate between the distribuited components of the system.
  3. SqlServer 2008 is used to store data on the server.
  4. SqlServer Compact Edition stores data for the mobile application.

Sync Framework is composed of several classes but the main important are the SyncProvider class and the SyncAgent class. SyncProviders and its derived classes ServerSyncProvider and ClientSyncProvider are used to interface data sources with the sync framework. SyncAgent gets a reference to two SyncProvider (a local sync provider and a remove syncprovider), then enumerates all the tables to update and finally makes the synchronization.
This is the code to sync two data sources in pseudo-C# language:


ServerSyncProvider remoteProvider = new ServerSyncProvider(...);
ClientSyncProvider localProvider = new ClientSyncProvider (...);
SyncAgent agent = new SyncAgent();
agent.RemoteProvider = remoteProvider;
agent.LocalProvider = localProvider;

agent.Synchronize();

Sync Framework includes different syncproviders out of the box. What we surely need is the DbServerSyncProvider (derived from ServerSyncProvider) which can be used to interface a server database engine like SqlServer and SqlCeClientSyncProvider (derived from ClientSyncProvider) which manages a SqlServer Compact Edition database. If you develop with VisualStudio you can gain access to a project template which creates for you all the code necessary to bind a SqlServer/SqlServerCE datasource with a Client/ServerSyncProvider, so the only thing to do is to call SyncAgent.Synchronize() when your user want to synchronize data.

At this point if we had to build a single-tier application our work should ends here. But things are more complicated because the DbServerSyncProvider(remoteProvider object) must be located on the server machine and on the other hand a SqlCeClientSyncProvider (localProvider object) must be instantiated by the mobile applications. Here WCF comes to help us with this task.

We'll create a WCF service running on the server machine that instantiates a DbServerSyncProvider object bound to the local SqlServer database. In addition it will expose a WCF datacontract interface that is exactly the same implemented by a ServerSyncProvider. The mobile application can instead instantiate a WCF client proxy connected to the server WCF service which can be passed with no modifications to the property SyncAgent.RemoteProvider just before call its Synchronize() method.

To build a project with Sync Framework you need to download and install the following packages:

  1. Then you may need SqlServer 2005 or 2008 in any version (express editions are enough).
  2. Windows Mobile SDK 6 is also required to build application for Windows Mobile Devices (http://www.microsoft.com/downloads/details.aspx?familyid=06111A3A-A651-4745-88EF-3D48091A390B&displaylang=en).
  3. Nortwind database is required if you want to run my sample project but you can just follow the sample to bind your custom database changing where needed connection string and table names.

Let's starts creating a new project under VS using WCF Service Library Template:

This create a WFC service with a dummy data contract called 'Service1'. The next step is to create the server sync provider bound to table 'customers' of the northwind sample database. So add a new item to the project selecting 'Local Database Cache' template under 'Data' category:

As item is created a wizard window appears. Use this wizard to select a connection string pointing to the Northwind database and to add table 'customers' on the left list. Note that we need only server synchronization here because client part is realized on the mobile application. So select 'Server Sync Only' under advanced options:

After you click OK on this window, a ServerSyncProvider-derived class is created and is named <'YourName'>ServerSyncProvider (in my case 'NorthwindServerSyncProvider'). At this point we need to expose the provider with WCF. So replace the dummy IService1 datacontract with a data contact called I<'YourName'>Service and implement it in a class called <'YourName'>Service. Following code can be copy and pasted directly in your project:

public class NorthwindService : INorthwindService

{

static NorthwindServerSyncProvider _serverSyncProvider = new NorthwindServerSyncProvider();

#region INorthwindService Memberspublic string GetServerVersion()

{

return Assembly.GetExecutingAssembly().ImageRuntimeVersion.ToString();

}

public SyncServerInfo GetServerInfo(SyncSession syncSession)

{

return _serverSyncProvider.GetServerInfo(syncSession);

}

public SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession)

{

return _serverSyncProvider.ApplyChanges(groupMetadata, dataSet, syncSession);

}

public SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession)

{

return _serverSyncProvider.GetChanges(groupMetadata, syncSession);

}

public SyncSchema GetSchema(string[] tableNames, SyncSession syncSession)

{

Collection<string> tables = new Collection<string>();

for (int i = 0; i < tableNames.Length; i++)

tables.Add(tableNames[i]);

return _serverSyncProvider.GetSchema(tables, syncSession);

}

#endregion

}

[XmlSerializerFormat] //VERY IMPORTANT ATTRIBUTE

[ServiceContract]

public interface INorthwindService

{

[
OperationContract]

string GetServerVersion();

#region sync service Server provider abstract methods

[OperationContract]

SyncServerInfo GetServerInfo(SyncSession syncSession);

[OperationContract]

SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession);

[OperationContract]

SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession); [OperationContract]

SyncSchema GetSchema(string[] tableNames, SyncSession syncSession);

#endregion

}

Note that I added a XmlSerializeFormat attribute to INorthwindService data contract to let WCF mobile implementation consume the service. In addition you have to change the WCF configuration in order to reflect the changed name of the data contract: open the App.Config and replace 'Service1' strings with 'NorthwindService'. Evenmore you need to change the binding from WSHttpBinding to BasicHttpBinding which is the only one supported by WCF Mobile implementation . You can find the correct App.Config file in the attached sample project.
Now if build and run the project WcfSvcHost should start showing the service correctly published:

Now focus on mobile application. Add a new Smart Device Project, selecting Windows Mobile 6 Prof SDK as platform and .NET CF 3.5.

Then add a reference to assemblies Microsoft.Synchronization.Data, Microsoft.Synchronization.Data.SqlServerCe, System.Runtime.Serialization and System.ServiceModel. You should now create a WCF service client proxy for the INorthwind service using the tool 'netcfsvcutil.exe'. I made this work for you and because a service for sync framework has always the same contract you can simply add the proxy classes copying it from my test project ('CFClientBase.cs' and 'NorthwindService.cs') renaming internal interface name as your service.

As last thing add a data grid to Form1 and a button which fires the synchronization. This is the code of the button click handler:

SqlCeConnection conn = new SqlCeConnection("data source = Northwind.sdf");

private void btnSync_Click(object sender, EventArgs e)

{

NorthwindServiceClient svc = new NorthwindServiceClient();

SqlCeClientSyncProvider clientProvider = new SqlCeClientSyncProvider(conn.ConnectionString, true);

ServerSyncProvider serverProvider = new ServerSyncProviderProxy(svc);

SyncAgent sa = new SyncAgent();

sa.Configuration.SyncTables.Add(

"Customers", TableCreationOption.CreateNewTableOrFail,Microsoft.Synchronization.Data.SyncDirection.Bidirectional);

 

sa.LocalProvider = clientProvider;

sa.RemoteProvider = serverProvider;

sa.Synchronize();

 

UpdateDataGrid();

}

private void UpdateDataGrid()

{

conn.Open();

SqlCeCommand cmd = new SqlCeCommand("SELECT * FROM Customers");

cmd.Connection = conn;

SqlCeResultSet dt = cmd.ExecuteResultSet(ResultSetOptions.Updatable | ResultSetOptions.Scrollable);

dataGrid.DataSource = dt;

}

Build the solution and start debug of the mobile application. You should see a datagrid filling the form and a button on bottom. Clicking the button a NorthwindServiceClient is created and a SyncAgent is initializated as shown in btnSync_Click() handler above. After that the data grid is populated with the updated list of Customers downloaded from the server.

Click below to download the sample project:

YouDev.WCF.rar (286.54 kb)

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
28 Comments