Wednesday, January 9, 2008

Use the Sync Framework with C#

Hi Guys

Micro soft introduce new framework for all type sync. This framework have varity type of the specify sync operation with database or filesystem.

List of those are,

1.ADO.Net

2.Common(File System)

You can downlaod SyncFramework from bellow url

http://www.microsoft.com/downloads/details.aspx?FamilyId=35E8F16E-AAA4-4919-8B3C-1CE4EA1F6552&displaylang=en

The Sync framework have managed class libraries. So we can code with C# or other your desired language (MS).

After download and installed , create a new Project with C# or your desired language.

I had create console application with C#

Afte you must add References Microsoft Synchronization

using System;
using System.IO;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Files;

public class FileSyncProviderSample
{
public static void Main( string [] args)
{
if (args.Length <>
string .IsNullOrEmpty(args[0]) || string .IsNullOrEmpty(args[1]) ||
! Directory .Exists(args[0]) || ! Directory .Exists(args[1]))
{
Console .WriteLine(
"Usage: FileSyncSample [valid directory path 1] [valid directory path 2]" );
return ;
}

string replica1RootPath = args[0];
string replica2RootPath = args[1];
string idFileName = "filesync.id" ;

SyncId replica1Id = GetReplicaId( Path .Combine(args[0], idFileName));
SyncId replica2Id = GetReplicaId( Path .Combine(args[1], idFileName));

try
{
// Set options for the sync operation
FileSyncOptions options = FileSyncOptions.ExplicitDetectChanges |
FileSyncOptions.RecycleDeletes | FileSyncOptions.RecycleOverwrites;

FileSyncScopeFilter filter = new FileSyncScopeFilter();
filter.FileNameExcludes.Add(idFileName); // Exclude the id file

// Explicitly detect changes on both replicas upfront, to avoid two change
// detection passes for the two-way sync
DetectChangesOnFileSystemReplica(
replica1Id, replica1RootPath, filter, options);
DetectChangesOnFileSystemReplica(
replica2Id, replica2RootPath, filter, options);

// Sync in both directions
SyncFileSystemReplicasOneWay(replica1Id, replica2Id,
replica1RootPath, replica2RootPath, filter, options);
SyncFileSystemReplicasOneWay(replica2Id, replica1Id,
replica2RootPath, replica1RootPath, filter, options);
}
catch ( Exception e)
{
Console .WriteLine( "\nException from File System Provider:\n" + e.ToString());
}
}

public static void DetectChangesOnFileSystemReplica(
SyncId replicaId, string replicaRootPath,
FileSyncScopeFilter filter, FileSyncOptions options)
{
FileSyncProvider provider = null ;

try
{
provider = new FileSyncProvider(replicaId, replicaRootPath, filter, options);
provider.DetectChanges();
}
finally
{
// Release resources
if (provider != null )
provider.Dispose();
}
}

public static void SyncFileSystemReplicasOneWay(
SyncId sourceReplicaId, SyncId destinationReplicaId,
string sourceReplicaRootPath, string destinationReplicaRootPath,
FileSyncScopeFilter filter, FileSyncOptions options)
{
FileSyncProvider sourceProvider = null ;
FileSyncProvider destinationProvider = null ;

try
{
sourceProvider = new FileSyncProvider(
sourceReplicaId, sourceReplicaRootPath, filter, options);
destinationProvider = new FileSyncProvider(
destinationReplicaId, destinationReplicaRootPath, filter, options);

destinationProvider.AppliedChange +=
new EventHandler (OnAppliedChange);
destinationProvider.SkippedChange +=
new EventHandler (OnSkippedChange);

SyncAgent agent = new SyncAgent();
agent.LocalProvider = sourceProvider;
agent.RemoteProvider = destinationProvider;
agent.Direction = SyncDirection.Upload; // Sync source to destination

Console .WriteLine( "Synchronizing changes to replica: " +
destinationProvider.RootDirectoryPath);
agent.Synchronize();
}
finally
{
// Release resources
if (sourceProvider != null ) sourceProvider.Dispose();
if (destinationProvider != null ) destinationProvider.Dispose();
}
}

public static void OnAppliedChange( object sender, AppliedChangeEventArgs args)
{
switch (args.ChangeType)
{
case ChangeType.Create:
Console .WriteLine( "-- Applied CREATE for file " + args.NewFilePath);
break ;
case ChangeType.Delete:
Console .WriteLine( "-- Applied DELETE for file " + args.OldFilePath);
break ;
case ChangeType.Overwrite:
Console .WriteLine( "-- Applied OVERWRITE for file " + args.OldFilePath);
break ;
case ChangeType.Rename:
Console .WriteLine( "-- Applied RENAME for file " + args.OldFilePath +
" as " + args.NewFilePath);
break ;
}
}

public static void OnSkippedChange( object sender, SkippedChangeEventArgs args)
{
Console .WriteLine( "-- Skipped applying " + args.ChangeType.ToString().ToUpper()
+ " for " + (! string .IsNullOrEmpty(args.CurrentFilePath) ?
args.CurrentFilePath : args.NewFilePath) + " due to error" );

if (args.Exception != null )
Console .WriteLine( " [" + args.Exception.Message + "]" );
}

public static SyncId GetReplicaId( string idFilePath)
{
SyncId replicaId = null ;

if ( File .Exists(idFilePath))
{
using ( StreamReader sr = File .OpenText(idFilePath))
{
string strGuid = sr.ReadLine();
if (! string .IsNullOrEmpty(strGuid))
replicaId = new SyncId( new Guid (strGuid));
}
}

if (replicaId == null )
{
using ( FileStream idFile = File .Open(
idFilePath, FileMode .OpenOrCreate, FileAccess .ReadWrite))
{
using ( StreamWriter sw = new StreamWriter (idFile))
{
replicaId = new SyncId( Guid .NewGuid());
sw.WriteLine(replicaId.GetGuidId().ToString( "D" ));
}
}
}

return replicaId;
}
}

basically sync framework work GUID as references. Because of Sync is time depend operation,so we must need a unique id for identification our file/DB is changed , removed and etc.

Con

The SyncFramework had greate feature for sync operation to all types of operation.

You can use the Sync framework for Database Sync , File System Sync,And Mobile decvice File Sync.

More from

http://msdn2.microsoft.com/en-us/sync/default.aspx

http://msdn2.microsoft.com/en-us/sync/bb887623.aspx

Best Regards
RRave

MCTS/MCPD