Question

I am trying to create a windows application using vs 2010 in c# which will sync two database where one database is on local machine and another on server. Here is my sample code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data.SqlServerCe;

namespace ExecuteExpressSync
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlConnection clientConn = new SqlConnection(@" Data Source=...; Initial Catalog= SqlServerSyncDb; Network Library=;Connection Timeout=15;Packet Size=4096;Integrated Security=no;User ID=.....;Password=....;Encrypt=no;");

            SqlConnection serverConn = new SqlConnection("Data Source=(local); Initial Catalog=SyncDB; Integrated Security=True");


            var providerl = new SqlSyncProvider("scopel", serverConn);
            var provider2 = new SqlSyncProvider("scopel", clientConn);

            // corvfig

            PrepareServerForProvisioning(providerl);

            PrepareClientForProvisioning(provider2, serverConn);

            //sync

            SyncOrchestrator sync = new SyncOrchestrator();
            sync.LocalProvider = providerl;
            sync.RemoteProvider = provider2;

            //((SqlCeSyncProvider)sync.LocalProvider).ApplyChangeFailed += new EventHandler<DbApplyChangeFailedEventArgs>(Program_ApplyChangeFailed);

            SyncOperationStatistics syncStats = sync.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);
        }

        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 PrepareServerForProvisioning(SqlSyncProvider provider)
        {

            SqlConnection connection = (SqlConnection)provider.Connection;

            SqlSyncScopeProvisioning config = new SqlSyncScopeProvisioning(connection); 

            if (!config.ScopeExists(provider.ScopeName))
            {

                DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription(provider.ScopeName); 

                scopeDesc.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable("Products", connection));
                scopeDesc.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable("Orders", connection));

                config.PopulateFromScopeDescription(scopeDesc);

                config.SetCreateTableDefault(DbSyncCreationOption.CreateOrUseExisting); 
                config.Apply();

            }

        }

        private static void PrepareClientForProvisioning(SqlSyncProvider provider, SqlConnection sourceConnection)
        {

            SqlSyncScopeProvisioning config = new SqlSyncScopeProvisioning((SqlConnection)provider.Connection); 

            if (!config.ScopeExists(provider.ScopeName))
            {

                DbSyncScopeDescription scopeDesc = SqlSyncDescriptionBuilder.GetDescriptionForScope(provider.ScopeName, sourceConnection); 
                config.PopulateFromScopeDescription(scopeDesc); 
                config.Apply();

            }

        }

    }
}

When i used this same code on two database running both on same machine it worked perfectly. But when i used plesk panel server database its getting an error saying your database is not provisioned. When I opened the server database I saw the tables have been created but there are no data. Another thing is that whenever i tried to see the table data it says "index out of bound array [Microsoft.SqlServer.Smo]".

Please Suggest what to do. Thanks in advance

Was it helpful?

Solution

chances are your Sync Fx objects are being created in non-dbo schema. you can force them to use the same schema during provisioning and during synchronization by setting the ObjectSchema property.

in your code above:

during provisioning set config.ObjectSchema="dbo"; or whatever schema you want to use.

during sync, set provider1.ObjectSchema="dbo"; or whatever schema you want to use.

the key thing is that whatever schema you used in the provisioning should be the same during synchronization.

if you dont dont want to deprovision, set the ObjectSchema="userx" (or whatever schema the objects were created) on the sync provider pointing to your plesk panel database

OTHER TIPS

This issue occurs because of an error in SSMS 2008 R2.

There are multiple workarounds with some limitations as mentioned below…

  1. Install Microsoft® SQL Server® 2012 Express – you can download it from here http://www.microsoft.com/en-us/download/details.aspx?id=29062. The only limitation is supported operating systems: Windows 7, Windows Server 2008 R2, Windows Server 2008 Service Pack 2, Windows Vista Service Pack 2.

  2. If you have SQL Server 2008 or 2008 R2 install you may choose for this fix -http://support.microsoft.com/kb/2459027

In this small projects I faced couple of problems.

  1. An error in SSMS 2008 R2.
  2. Synchronize error [Database is not provisioned].
  3. Object Schema problem.

Problem 1:

This problem occurred because of database version difference. My local machine Database is SQL Server 2008 r2 and plesk panel database is SQL Server 2005.

SOLUTION:

 Updated my local machine database to service pack 2. 

Problem 2 & Problem 3

 Problem 2 and 3 are related. In sql server 2008 the default object schema is "dbo" [ex. dbo.tablename] and in sql server 2005 default object is "[DATABASENAME]" [ex. TestSync.tablename considering database name is TestSync]. That's why the sync error occurred.

 So to fix the problem I tried to set the object schema manually from within the code and set `config.ObjectSchema = "dbo";` in client provisioning.

 But surprisingly it didn't work at all. The plesk panel server database was still creating its default object schema [TestSync.tablename]. When I tried debugging the code I learned that if I set the object schema to "dbo" it takes a null value and really don't know the reason for that.

SOLUTION

  So I set the object schema to ".dbo". 

config.ObjectSchema = ".dbo";

And now it works perfectly. Here is the complete working code...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data.SqlServerCe;

namespace ExecuteExpressSync
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlConnection clientConn = new SqlConnection("Data Source=208.91.198.174; Initial Catalog=RANAJOYDADIGI;Integrated Security=no;User ID=RANAJOYDADIGI;Password=RANAJOYDADIGI;Encrypt=no;Integrated Security=No");

            SqlConnection serverConn = new SqlConnection("Data Source=(local); Initial Catalog=ANIRUDDHADHARTEST; Integrated Security=True");

            var providerl = new SqlSyncProvider("scopel", serverConn);
            var provider2 = new SqlSyncProvider("scopel", clientConn);

            // corvfig

            PrepareServerForProvisioning(providerl);

            PrepareClientForProvisioning(provider2, serverConn);

            //sync

            SyncOrchestrator sync = new SyncOrchestrator();

            sync.LocalProvider = providerl;
            sync.RemoteProvider = provider2;            

            SyncOperationStatistics syncStats = sync.Synchronize();

            //Deprovision

            deprovisionServerClient(providerl);
            deprovisionServerClient(provider2);

            serverConn.Close();

            serverConn.Dispose();

            clientConn.Close();

            clientConn.Dispose();
        }       

        private static void PrepareServerForProvisioning(SqlSyncProvider provider)
        {

            SqlConnection connection = (SqlConnection)provider.Connection;

            SqlSyncScopeProvisioning config = new SqlSyncScopeProvisioning(connection);


            if (!config.ScopeExists(provider.ScopeName))
            {

                DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription(provider.ScopeName);

                scopeDesc.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable("dbo.Products", connection));
                scopeDesc.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable("dbo.Orders", connection));

                config.PopulateFromScopeDescription(scopeDesc);

                config.SetCreateTableDefault(DbSyncCreationOption.CreateOrUseExisting);

                config.Apply();

            }

        }

        private static void PrepareClientForProvisioning(SqlSyncProvider provider, SqlConnection sourceConnection)
        {

            SqlSyncScopeProvisioning config = new SqlSyncScopeProvisioning((SqlConnection)provider.Connection);
            config.ObjectSchema = ".dbo";

            if (!config.ScopeExists(provider.ScopeName))
            {

                DbSyncScopeDescription scopeDesc = SqlSyncDescriptionBuilder.GetDescriptionForScope(provider.ScopeName, sourceConnection);
                config.PopulateFromScopeDescription(scopeDesc);
                config.Apply();

            }

        }

        private static void deprovisionServerClient(SqlSyncProvider provider)
        {
            SqlSyncScopeDeprovisioning serverSqlDepro = new SqlSyncScopeDeprovisioning((SqlConnection)provider.Connection);
            serverSqlDepro.DeprovisionScope(provider.ScopeName);
            serverSqlDepro.DeprovisionStore();
        }

    }
}

Finally thank you everyone for the help you have provided.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top