예제 #1
0
        static void Main(string[] args)
        {
            // Create the connections over which provisioning and sycnhronization
            // are performed. The Utility class handles all functionality that is not
            //directly related to synchronization, such as holding connection
            //string information and making changes to the server database.
            SqlConnection   serverConn      = new SqlConnection(Utility.ServerConnString);
            SqlConnection   clientSqlConn   = new SqlConnection(Utility.ClientSqlConnString);
            SqlCeConnection clientSqlCeConn = new SqlCeConnection(Utility.ClientSqlCeConnString);

            // Create a scope named "filtered_customer", and add two tables to the scope.
            // GetDescriptionForTable gets the schema of each table, so that tracking
            // tables and triggers can be created for that table.
            //<snippetOCSv3_CS_Basic_SqlPeer_ScopeDesc>
            DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription("filtered_customer");

            scopeDesc.Tables.Add(
                SqlSyncDescriptionBuilder.GetDescriptionForTable("Customer", serverConn));
            scopeDesc.Tables.Add(
                SqlSyncDescriptionBuilder.GetDescriptionForTable("CustomerContact", serverConn));
            //</snippetOCSv3_CS_Basic_SqlPeer_ScopeDesc>

            // Create a provisioning object for "filtered_customer" and specify that
            // base tables should not be created (They already exist in SyncSamplesDb_SqlPeer1).
            //<snippetOCSv3_CS_Basic_SqlPeer_ServerConfig>
            SqlSyncScopeProvisioning serverConfig = new SqlSyncScopeProvisioning(scopeDesc);

            serverConfig.CreateTableDefault = DbSyncCreationOption.Skip;

            // Specify which column(s) in the Customer table to use for filtering data,
            // and the filtering clause to use against the tracking table.
            // "[side]" is an alias for the tracking table.
            serverConfig["Customer"].AddFilterColumn("CustomerType");
            serverConfig["Customer"].FilterClause = "[side].[CustomerType] = 'Retail'";

            // Configure the scope and change tracking infrastructure.
            serverConfig.Apply(serverConn);

            // Write the configuration script to a file. You can modify
            // this script if necessary and run it against the server
            // to customize behavior.
            File.WriteAllText("SampleConfigScript.txt",
                              serverConfig.Script("SyncSamplesDb_SqlPeer1"));
            //</snippetOCSv3_CS_Basic_SqlPeer_ServerConfig>


            // Retrieve scope information from the server and use the schema that is retrieved
            // to provision the SQL Server and SQL Server Compact client databases.

            //<snippetOCSv3_CS_Basic_SqlPeer_ClientConfig>
            // This database already exists on the server.
            DbSyncScopeDescription   clientSqlDesc   = SqlSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", serverConn);
            SqlSyncScopeProvisioning clientSqlConfig = new SqlSyncScopeProvisioning(clientSqlDesc);

            clientSqlConfig.Apply(clientSqlConn);

            // This database does not yet exist.
            Utility.CreateSqlCeDatabase();
            DbSyncScopeDescription     clientSqlCeDesc   = SqlSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", serverConn);
            SqlCeSyncScopeProvisioning clientSqlCeConfig = new SqlCeSyncScopeProvisioning(clientSqlCeDesc);

            clientSqlCeConfig.Apply(clientSqlCeConn);
            //</snippetOCSv3_CS_Basic_SqlPeer_ClientConfig>


            // Initial synchronization sessions. 7 rows are synchronized:
            // all rows (4) from CustomerContact, and the 3 rows from Customer
            // that satisfy the filtering criteria.
            //<snippetOCSv3_CS_Basic_SqlPeer_InitialSync>
            SampleSyncOrchestrator  syncOrchestrator;
            SyncOperationStatistics syncStats;

            // Data is downloaded from the server to the SQL Server client.
            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlSyncProvider("filtered_customer", clientSqlConn),
                new SqlSyncProvider("filtered_customer", serverConn)
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "initial");

            // Data is downloaded from the SQL Server client to the
            // SQL Server Compact client.
            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlCeSyncProvider("filtered_customer", clientSqlCeConn),
                new SqlSyncProvider("filtered_customer", clientSqlConn)
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "initial");
            //</snippetOCSv3_CS_Basic_SqlPeer_InitialSync>


            // Make changes on the server: 1 insert, 1 update, and 1 delete.
            Utility.MakeDataChangesOnServer();


            // Synchronize again. Three changes were made on the server, but
            // only two of them applied to rows that are in the "filtered_customer"
            // scope. The other row is not synchronized.
            // Notice that the order of synchronization is different from the initial
            // sessions, but the two changes are propagated to all nodes.
            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlCeSyncProvider("filtered_customer", clientSqlCeConn),
                new SqlSyncProvider("filtered_customer", serverConn)
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "subsequent");

            syncOrchestrator = new SampleSyncOrchestrator(
                new SqlSyncProvider("filtered_customer", clientSqlConn),
                new SqlCeSyncProvider("filtered_customer", clientSqlCeConn)
                );
            syncStats = syncOrchestrator.Synchronize();
            syncOrchestrator.DisplayStats(syncStats, "subsequent");

            serverConn.Close();
            serverConn.Dispose();
            clientSqlConn.Close();
            clientSqlConn.Dispose();
            clientSqlCeConn.Close();
            clientSqlCeConn.Dispose();

            Console.Write("\nPress any key to exit.");
            Console.Read();
        }
예제 #2
0
        private void UpdateExistingScopeProvision(SqlSyncScopeProvisioning provision, SqlConnection conn, bool isServer)
        {
            string alterScopeSql = string.Empty;

            provision.SetCreateProceduresDefault(DbSyncCreationOption.Create);
            provision.SetUseBulkProceduresDefault(true);

            provision.SetCreateTrackingTableDefault(DbSyncCreationOption.CreateOrUseExisting);
            var provisioningScript = provision.Script();
            //alterScopeSql = provision.Script();

            var stringBuilder = new StringBuilder();
            var changedTables = tables.Where(t => t.InScope.Value == 1).ToList();

            foreach (var changedTable in changedTables)
            {
                var tableName = isServer ? changedTable.ServerTableName : changedTable.ClientTableName;
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_bulkinsert];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_bulkupdate];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_bulkdelete];");
                stringBuilder.AppendLine("DROP TYPE [" + tableName + "_BulkType];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_selectchanges];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_selectrow];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_insert];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_update];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_delete];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_insertmetadata];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_updatemetadata];");
                stringBuilder.AppendLine("DROP PROCEDURE [" + tableName + "_deletemetadata];");
            }

            // append the sync provisioning script after the drop statements
            alterScopeSql = stringBuilder.Append(provisioningScript).ToString();

            int x           = alterScopeSql.IndexOf("N'<SqlSyncProviderScopeConfiguration");
            int y           = alterScopeSql.IndexOf("</SqlSyncProviderScopeConfiguration>");
            var configEntry = alterScopeSql.Substring(x, y - x) + "</SqlSyncProviderScopeConfiguration>'";

            x             = alterScopeSql.IndexOf("- BEGIN Add scope");
            y             = alterScopeSql.IndexOf("- END Add Scope");
            alterScopeSql = alterScopeSql.Remove(x, y - x);

            alterScopeSql = alterScopeSql.Replace("scope_status = 'C'", "config_data=" + configEntry);

            x             = alterScopeSql.IndexOf("WHERE [config_id] =");
            alterScopeSql = alterScopeSql.Remove(x, alterScopeSql.Length - x);

            alterScopeSql = alterScopeSql
                            + " WHERE [config_id] = (SELECT scope_config_id FROM scope_info WHERE sync_scope_name='"
                            + configuration.ScopeName + "')";

            using (var connection = new SqlConnection(conn.ConnectionString))
            {
                connection.Open();
                string[] commands = alterScopeSql.Split(new string[] { "GO\r\n", "GO ", "GO\t", "GO" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var c in commands)
                {
                    var command = new SqlCommand(c, connection);
                    command.ExecuteNonQuery();
                }
            }
        }
예제 #3
0
        private static void Provision(SelectedConfigSections selectedConfig, DbSyncScopeDescription scopeDescription, bool script, DirectoryInfo workingDirectory)
        {
            try
            {
                SqlSyncScopeProvisioning prov =
                    new SqlSyncScopeProvisioning(new SqlConnection(selectedConfig.SelectedTargetDatabase.GetConnectionString()),
                                                 scopeDescription,
                                                 selectedConfig.SelectedSyncScope.IsTemplateScope
                            ? SqlSyncScopeProvisioningType.Template
                            : SqlSyncScopeProvisioningType.Scope);

                // Note: Deprovisioning does not work because of a bug in the provider when you set the ObjectSchema property to “dbo”.
                // The workaround is to not set the property (it internally assumes dbo in this case) so that things work on deprovisioning.
                if (!String.IsNullOrEmpty(selectedConfig.SelectedSyncScope.SchemaName))
                {
                    prov.ObjectSchema = selectedConfig.SelectedSyncScope.SchemaName;
                }

                foreach (SyncTableConfigElement tableElement in selectedConfig.SelectedSyncScope.SyncTables)
                {
                    // Check and set the SchemaName for individual table if specified
                    if (!string.IsNullOrEmpty(tableElement.SchemaName))
                    {
                        prov.Tables[tableElement.GlobalName].ObjectSchema = tableElement.SchemaName;
                    }

                    prov.Tables[tableElement.GlobalName].FilterClause = tableElement.FilterClause;
                    foreach (FilterColumnConfigElement filterCol in tableElement.FilterColumns)
                    {
                        prov.Tables[tableElement.GlobalName].FilterColumns.Add(
                            scopeDescription.Tables[tableElement.GlobalName].Columns[filterCol.Name]);
                    }
                    foreach (FilterParameterConfigElement filterParam in tableElement.FilterParameters)
                    {
                        CheckFilterParamTypeAndSize(filterParam);
                        prov.Tables[tableElement.GlobalName].FilterParameters.Add(new SqlParameter(filterParam.Name,
                                                                                                   (SqlDbType)Enum.Parse(typeof(SqlDbType), filterParam.SqlType, true)));
                        prov.Tables[tableElement.GlobalName].FilterParameters[filterParam.Name].Size = filterParam.DataSize;
                    }
                }

                // enable bulk procedures.
                prov.SetUseBulkProceduresDefault(selectedConfig.SelectedSyncScope.EnableBulkApplyProcedures);

                // Create a new set of enumeration stored procs per scope.
                // Without this multiple scopes share the same stored procedure which is not desirable.
                prov.SetCreateProceduresForAdditionalScopeDefault(DbSyncCreationOption.Create);

                if (selectedConfig.SelectedSyncScope.IsTemplateScope)
                {
                    if (!script)
                    {
                        if (!prov.TemplateExists(selectedConfig.SelectedSyncScope.Name))
                        {
                            Log("Provisioning Database {0} for template scope {1}...",
                                selectedConfig.SelectedTargetDatabase.Name,
                                selectedConfig.SelectedSyncScope.Name);
                            prov.Apply();
                        }
                        else
                        {
                            throw new InvalidOperationException(
                                      string.Format(
                                          "Database {0} already contains a template scope {1}. Please deprovision the scope and retry.",
                                          selectedConfig.SelectedTargetDatabase.Name,
                                          selectedConfig.SelectedSyncScope.Name));
                        }
                    }
                    else
                    {
                        SaveScript("provision.sql", prov.Script(), workingDirectory);
                    }
                }
                else
                {
                    if (!script)
                    {
                        if (!prov.ScopeExists(selectedConfig.SelectedSyncScope.Name))
                        {
                            Log("Provisioning Database {0} for scope {1}...", selectedConfig.SelectedTargetDatabase.Name,
                                selectedConfig.SelectedSyncScope.Name);


                            prov.Apply();
                        }
                        else
                        {
                            throw new InvalidOperationException(
                                      string.Format(
                                          "Database {0} already contains a scope {1}. Please deprovision the scope and retry.",
                                          selectedConfig.SelectedTargetDatabase.Name,
                                          selectedConfig.SelectedSyncScope.Name));
                        }
                    }
                    else
                    {
                        SaveScript("provision.sql", prov.Script(), workingDirectory);
                    }
                }
            }
            catch (ConfigurationErrorsException)
            {
                throw;
            }
            catch (InvalidOperationException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new InvalidOperationException(
                          "Unexpected error when executing the Provisioning command. See inner exception for details.", e);
            }
        }