I am developing a Winforms application with .NET Framework 4.6 that runs online as well as offline. The cloud DB server is SQL Server 2016 and client will use SQL Server CE 4.0.
I intend to achieve this using the Microsoft Sync framework to synchronize the data between the 2 servers.
This is my code:
public static void Synchronize(string scopeName, string serverConnectionString, string clientConnectionString)
{
Initialize(scopeName, serverConnectionString, clientConnectionString);
Synchronize(scopeName, serverConnectionString, clientConnectionString, SyncDirectionOrder.UploadAndDownload);
CleanUp(scopeName, serverConnectionString, clientConnectionString);
}
private static void Initialize(string scope_name, string serverConnectionString, string clientConnectionString)
{
// SQL Server Connection
SqlConnection serverConnection = new SqlConnection(serverConnectionString);
// Scope Description
DbSyncScopeDescription svrScopeDescription = new DbSyncScopeDescription(scope_name);
// Table List
ArrayList tablesList= new ArrayList {
"SYNC_TEST"
/* OTHER TABLES */
};
// Table/scope Descption
foreach (String table in tablesList)
{
DbSyncTableDescription svrTableDescription = SqlSyncDescriptionBuilder.GetDescriptionForTable(table, serverConnection);
svrTableDescription.Columns["PK"].IsPrimaryKey = true;
svrScopeDescription.Tables.Add(svrTableDescription);
}
// Apply SQL Server Scope Provision
SqlSyncScopeProvisioning serverProvision = new SqlSyncScopeProvisioning(serverConnection, svrScopeDescription);
serverProvision.SetCreateTableDefault(DbSyncCreationOption.Skip);
serverProvision.Apply();
// create a connection to the SyncCompactDB database
SqlCeConnection clientConn = new SqlCeConnection(clientConnectionString);
// get the description of Scope from the SyncDB server database
DbSyncScopeDescription clntScopeDescription = SqlSyncDescriptionBuilder.GetDescriptionForScope(scope_name, serverConnection);
// create CE provisioning object based on the Scope
SqlCeSyncScopeProvisioning clientProvision = new SqlCeSyncScopeProvisioning(clientConn, clntScopeDescription);
clientProvision.SetCreateTableDefault(DbSyncCreationOption.CreateOrUseExisting);
// starts the provisioning process
clientProvision.Apply();
}
private static void Synchronize(string scopeName, string serverConnectionString, string clientConnectionString, SyncDirectionOrder syncDirectionOrder)
{
try
{
// create a connection to the SyncCompactDB database
SqlCeConnection clientConn = new SqlCeConnection(clientConnectionString);
// create a connection to the SyncDB server database
SqlConnection serverConn = new SqlConnection(serverConnectionString);
// create the sync orchestrator
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();
// set local provider of orchestrator to a CE sync provider associated with the
// ProductsScope in the SyncCompactDB compact client database
syncOrchestrator.LocalProvider = new SqlCeSyncProvider(scopeName, clientConn);
// set the remote provider of orchestrator to a server sync provider associated with
// the ProductsScope in the SyncDB server database
syncOrchestrator.RemoteProvider = new SqlSyncProvider(scopeName, serverConn);
// set the direction of sync session to Upload and Download
syncOrchestrator.Direction = syncDirectionOrder;
// subscribe for errors that occur when applying changes to the client
((SqlCeSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed);
// subscribe for errors that occur when applying changes to the server
((SqlSyncProvider)syncOrchestrator.RemoteProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed);
// execute the synchronization process
SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();
// print statistics
Console.WriteLine("Start Time: " + syncStats.SyncStartTime);
Console.WriteLine("Total Changes Uploaded: " + syncStats.UploadChangesTotal);
Console.WriteLine("Total Changes Downloaded: " + syncStats.DownloadChangesTotal);
Console.WriteLine("Complete Time: " + syncStats.SyncEndTime);
Console.WriteLine(String.Empty);
}
catch (Exception e)
{
String x = e.Message;
String y = e.StackTrace;
String z = e.Source;
String x1 = e.InnerException.ToString();
String y1 = e.TargetSite.ToString();
String z1 = e.Data.ToString();
}
}
private static void dbProvider_SyncProcessFailed(object sender, DbApplyChangeFailedEventArgs e)
{
throw new NotImplementedException();
}
private static void dbProvider_SyncProgress(object sender, DbSyncProgressEventArgs e)
{
throw new NotImplementedException();
}
static void Program_ApplyChangeFailed(object sender, DbApplyChangeFailedEventArgs e)
{
// display conflict type
Console.WriteLine(e.Conflict.Type);
// display error message
Console.WriteLine(e.Error);
}
private static void CleanUp(string scopeName, string serverConnectionString, string clientConnectionString)
{
SqlConnection serverConnection = new SqlConnection(serverConnectionString);
SqlCeConnection clientConnection = new SqlCeConnection(clientConnectionString);
SqlSyncScopeDeprovisioning serverDeprovisioning = new SqlSyncScopeDeprovisioning(serverConnection);
SqlCeSyncScopeDeprovisioning clientDeprovisioning = new SqlCeSyncScopeDeprovisioning(clientConnection);
serverDeprovisioning.DeprovisionScope(scopeName);
serverDeprovisioning.DeprovisionStore();
clientDeprovisioning.DeprovisionScope(scopeName);
clientDeprovisioning.DeprovisionStore();
}
This works well if the direction is only download.
However when I change the direction to Upload, UploadDownload or DownloadUplaod I am getting an error for every column with data type real of float.
Could some one please help me out, towards what I am doing wrong?
I had the same issue. No support whatsoever on internet. It started working fine once I converted from float to decimal. Float is considered as approx./rough datatype and decimal is of exact precision and hence it works. I even tried the library dotmim as mentioned but it also didn't work. Not much support for it either.