Microsoft Sync Framework同步数据库 3:针对同步进行设置

针对同步进行设置

在可以使用 Sync Framework 同步数据库之前,需要通过称为“设置(provisioning)”的流程配置它。所需的设置类型因数据库类型而异。本篇提供有关设置 SQL Server 和 SQL Server Compact 数据库的背景信息、操作步骤以及完整代码示例。

了解设置和取消设置(Provision and Deprovision)

为同步配置数据库的第一步是定义一个作用域,该作用域标识要同步的内容。在您定义同步作用域后,就可以使用该同步作用域来设置数据库,以便创建变更跟踪和元数据管理基础结构,该基础结构由元数据表、触发器和存储过程构成。在设置了某一数据库后,可以通过使用某一提供程序(例如 SqlSyncProvider)来表示该数据库和使用 SyncOrchestrator 对象管理同步会话并连接到其他同步提供程序以实现数据同步。为同步设置数据库是有别于与其他数据库同步的单独任务,这部分代码通常位于单独的应用程序中。

设置(Provision)

在设置(Provision)数据库时,通常会在数据库中创建以下某些或全部元素:

  • 在同步作用域中包含的基表。
  • 作用域中每个基表的一个跟踪表。该跟踪表跟踪对关联基表进行的变更。
  • 在直接对基表进行更改时更新跟踪表的触发器。
  • 用于同步操作的存储过程,例如枚举变更、插入变更、更新数据或删除数据。通过设置对象的SetUseBulkProceduresDefault方法可以为SQL Server 2008 和 SQL Azure 数据库创建使用表值函数一次执行多行的插入、更新和删除操作的成批过程。
  • 包含同步作用域信息的特殊表,例如 scope_info 表。如果这些表尚不存在,则创建这些表。

数据库设置对象提供了相应方法来控制上面这些同步元素的创建,比如:基表创建由 SetCreateTableDefault 方法控制,跟踪表创建由 SetCreateTrackingTableDefault 方法控制。此外,同步元素可以创建在数据库的单独架构(Schema)中,这是通过 SqlSyncScopeProvisioning类的ObjectSchema 属性实现的。

可通过调用 SqlSyncScopeProvisioning.Apply 或 SqlCeSyncScopeProvisioning.Apply方法直接应用设置;或者,对于 SQL Server 数据库,可以创建一个脚本并在以后运行该脚本来设置数据库。若要创建设置脚本,请调用 SqlSyncScopeProvisioning.Script 方法。

取消设置(Deprovision)

如果您不再需要某一作用域,则可以通过调用SqlSyncScopeDeprovisioning.DeprovisionScope 或 SqlCeSyncScopeDeprovisioning.DeprovisionScope,删除该作用域及其关联的元数据表、触发器和存储过程。在已删除某一作用域后,该作用域不再用于同步。如果某一数据库元素(例如元数据表)由多个作用域使用,则在使用该元素的最后一个作用域被删除前,将不删除该元素。例如,您具有名为 Customers 的一个表,并且定义两个分别名为 RetailCustomers 和 WholesaleCustomers 的作用域,并且这两个作用域包含 Customers 表。在您删除 WholesaleCustomers 作用域时,用于 Customers 表的元数据表不删除,因为它仍由 RetailCustomers 作用域使用。

如果您使用基于参数的筛选器来筛选 SQL Server 或 SQL Azure 数据库中的同步数据,则首先创建一个筛选器模板,然后基于该筛选器模板创建筛选的作用域。您还可以通过调用 DeprovisionTemplate,轻松地删除该筛选器模板和基于该模板创建的所有经过筛选的作用域,以及所有关联的元数据表、触发器和存储过程。例如,您创建一个 customerstate_template 模板,该模板通过使用 state 参数进行筛选。您基于 customerstate_template 创建两个经过筛选的作用域 customers_WA 和 customers_OR。在您删除 customerstate_template 时,customers_WA 和 customers_OR 也删除。

您还可以通过调用SqlSyncScopeDeprovisioning.DeprovisionStore 或 SqlCeSyncScopeDeprovisioning.DeprovisionStore,从数据库中删除所有作用域和筛选器以及所有同步元数据表、触发器和存储过程。此外,因为删除单独的作用域和筛选器模板将仅删除作用域级别和模板级别的元数据,而不删除数据库级别的元数据,所以,SqlSyncScopeDeprovisioning.DeprovisionStore 或 SqlCeSyncScopeDeprovisioning.DeprovisionStore 可用于在删除了所有作用域和模板后清除剩余的同步元数据表。

 

设置数据库

同步作用域和同步模板

我们之前已经了解到,同步作用域是对进行同步的对象的一种逻辑分组。对于数据库同步,一个同步组通常是一组数据表,并且数据表可以被过滤。同时一个数据表可以被包含在一个或多个同步组中。

有些时候,我们需要使用基于参数的筛选器来筛选 SQL Server 或 SQL Azure 数据库中的同步数据,则首先创建一个筛选器模板,然后基于该筛选器模板创建筛选的作用域。比如,每个销售人员只对自己相关的订单数据感兴趣,那么我们就需要针对每个销售人员创建同步作用域,这时,我们就可以使用同步模板来简化同步作用域的创建过程,甚至通过订阅的手段来实现这一过程的自动化。关于筛选器模板的详细介绍请参考下篇“如何为数据库同步筛选数据”。

定义同步作用域

下面的代码定义了一个名为filtered_customer 的同步作用域,并为其添加了两个表:Customer和CustomerContact。因为这些表已经存在于服务器数据库之中,所以使用GetDescriptionForTable方法来检索表的架构。Customer表的所有列都包含在同步作用域中,但是CustomerContact表只包含了两列。

            DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription("filtered_customer");

// Definition for Customer.
DbSyncTableDescription customerDescription =
SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.Customer", serverConn);

scopeDesc.Tables.Add(customerDescription);

// Definition for CustomerContact, including the list of columns to include.
Collection<string> columnsToInclude = new Collection<string>();
columnsToInclude.Add("CustomerId");
columnsToInclude.Add("PhoneType");
DbSyncTableDescription customerContactDescription =
SqlSyncDescriptionBuilder.GetDescriptionForTable("Sales.CustomerContact", columnsToInclude, serverConn);

scopeDesc.Tables.Add(customerContactDescription);

设置服务器数据库

下面的代码为filtered_customer 同步作用域创建了一个设置对象,并且指定所有同步元素创建在"Sync"数据库架构中。代码还为Customer表指定了一个过滤条件,只有满足该条件的数据行才会被同步。定义一个过滤条件分为两部分:调用AddFilterColumn指定过滤列名为”CustomerType”,它会被添加到变更跟踪表以跟踪Customer表的改变。调用FilterClause指定过滤条件本身,它是不包含WHERE关键字的WHERE子句。[side]是变更跟踪表的别名。定义好设置选项后,Apply方法会在服务器数据库中创建变更跟踪基础结构,并且把设置脚本写到一个文件中。

            SqlSyncScopeProvisioning serverConfig = new SqlSyncScopeProvisioning(serverConn, scopeDesc);
serverConfig.ObjectSchema = "Sync";

// 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.Tables["Sales.Customer"].AddFilterColumn("CustomerType");
serverConfig.Tables["Sales.Customer"].FilterClause = "[side].[CustomerType] = 'Retail'";

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

// 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());

设置客户端数据库

我们可以通过两种方式来设置客户端数据库:

1. 基于从服务器或另外的客户端数据库获取的scope/作用域信息,完全初始化一个SQL Server或SQL Server Compact客户端数据库。我们可以通过SqlSyncDescriptionBuilder和SqlCeSyncDescriptionBuilder对象来获取同步作用域的架构信息,从而在客户端数据库创建同步对象。

2. 通过一个已经存在的客户端数据库来对一个SQL Server Compact客户端数据库进行快照初始化。

快照初始化的主要目的是减少初始化客户端数据库所需的时间。更多关于快照初始化的知识请参照本篇“使用快照设置数据库”的详细介绍。

下面的代码示例首先从服务器获取同步作用域信息,并使用它们来设置一个SQL Server Compact客户端数据库。然后,基于该SQL Server Compact客户端数据库的作用域信息来设置另一个SQL Server客户端数据库。

            // 创建一个SQL Server Compact数据库并用从服务器端获取的作用域信息来设置它
// Compact数据库不支持单独的schema,
// 所以我们通过为所有的同步对象增加前缀"Sync"来使他们易于区分
Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync1, true);
Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync2, false);
DbSyncScopeDescription clientSqlCe1Desc = SqlSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", null, "Sync", serverConn);
SqlCeSyncScopeProvisioning clientSqlCe1Config = new SqlCeSyncScopeProvisioning(clientSqlCe1Conn, clientSqlCe1Desc);
clientSqlCe1Config.ObjectPrefix = "Sync";
clientSqlCe1Config.Apply();

// 通过从SQL Server Compact数据库中获取的同步作用域信息来设置一个SQL Server客户端数据库
// 当然我们也可以从服务器端获取作用域信息
DbSyncScopeDescription clientSqlDesc = SqlCeSyncDescriptionBuilder.GetDescriptionForScope("filtered_customer", "Sync", clientSqlCe1Conn);
SqlSyncScopeProvisioning clientSqlConfig = new SqlSyncScopeProvisioning(clientSqlConn, clientSqlDesc);
clientSqlConfig.ObjectSchema = "Sync";
clientSqlConfig.Apply();

 

取消设置数据库

下面的代码示例为我们展示了如何:

  • 在客户端数据库中取消设置一个同步作用域
  • 在服务器数据库中取消设置筛选器模板和相关的作用域
  • 完全取消设置一个客户端数据库,这样所有的同步对象都会被删除

删除一个作用域

下面的示例在一个SQL Server客户端数据库中删除RetailCustomers作用域。同时,删除作用域的脚本被保存到了一个文件之中,这个脚本可以用来执行以删除其他数据库中的RetailCustomers作用域。淡然,这个步骤对于删除一个同步作用域来说是可选的。

            // 在SQL Server客户端数据库中删除RetailCustomers作用域
SqlSyncScopeDeprovisioning clientSqlDepro = new SqlSyncScopeDeprovisioning(clientSqlConn);

// 首先把取消设置的SQL脚本保存下来,以便取消设置其他的SQL Server客户端数据库
// 这一步是可选的
File.WriteAllText("SampleDeprovisionScript.txt",
clientSqlDepro.ScriptDeprovisionScope("RetailCustomers"));

// 删除作用域
clientSqlDepro.DeprovisionScope("RetailCustomers");

删除一个筛选器模板

在删除一个筛选器模板之前,我们通常需要查看从这个筛选器模板创建出来的同步作用域,因为当这个筛选器模板被删除(Deprovision)时,所有这些作用域也会被删除。下面的SQL脚本可以用来查找由customertype_template筛选器模板所创建的筛选作用域。

-- Find all filtered scopes that were created from the filtered scope template named 'customertype_template'.

select sync_scope_name from scope_info
where scope_config_id =
(select template_config_id from scope_templates
where template_name = N'customertype_template')

下面的示例从SQL Server服务器数据库中删除customertype_template筛选器模板。在删除该模板的同时也会删除由它创建出来的作用域RetailCustomers和WholesaleCustomers。

            // 从服务器数据库中删除"customertype_template"模板
// 这样也会删除所有依赖与该模板的作用域
SqlSyncScopeDeprovisioning serverSqlDepro = new SqlSyncScopeDeprovisioning(serverConn);
serverSqlDepro.DeprovisionTemplate("customertype_template");

删除所有同步对象

下面的示例从一个SQL Server Compact客户端数据库中删除所有的同步对象,包括:同步元数据表、触发器和存储过程。

            // 在SQL Server Compact数据库这哦你删除所有的同步对象
SqlCeSyncScopeDeprovisioning clientSqlCeDepro = new SqlCeSyncScopeDeprovisioning(clientSqlCe1Conn);
clientSqlCeDepro.DeprovisionStore();

 

使用快照设置数据库

如果我们需要对多个SQL Server Compact数据库的同步进行设置,那么我们可以使用数据库快照来减少初始化所需的时间。一个快照是特别准备的,包含了表架构、数据(可选)、和变更跟踪基础结构的SQL Server Compact数据库。在我们对一个SQL Server Compact数据库作完全初始化后,我们可以为其创建一个快照,该快照可以拷贝至其他需要同步的SQL Server Compact数据库。对数据库应用快照的过程比完全初始化要高效得多。

下面的示例为我们展示了通过从服务器数据库获取的作用域信息来设置Compact数据库,然后使用该数据库的快照来初始化另外一个数据库。

        static void SynchronizationUsingSnapshot()
{
// 通过从服务器数据库获取的作用域信息来设置Compact数据库SyncCompactDB2.sdf
SqlCeConnection clientConn = new SqlCeConnection(@"Data Source='D:\Sync Framework\CompactDB\SyncCompactDB2.sdf'");
SqlConnection serverConn = new SqlConnection("Data Source=localhost; Initial Catalog=SyncDB; Integrated Security=True");
DbSyncScopeDescription scopeDesc = SqlSyncDescriptionBuilder.GetDescriptionForScope("ProductsScope", serverConn);
SqlCeSyncScopeProvisioning clientProvision = new SqlCeSyncScopeProvisioning(clientConn, scopeDesc);
clientProvision.Apply();

// 从SQL Server Compact数据库创建一个快照,该快照将用于初始化其他的Compact数据库
// 尽管我们可以从其他数据库获取作用域信息来初始化,但快照的使用为Compact数据库提供了一个更加快捷方便的部署方案。
// SyncCompactDB3.sdf为不存在的Compact数据库,将在GenerateSnapshot方法中自动创建
string newCompactDB = @"D:\Sync Framework\CompactDB\SyncCompactDB3.sdf";
SqlCeSyncStoreSnapshotInitialization syncStoreSnapshot = new SqlCeSyncStoreSnapshotInitialization();
syncStoreSnapshot.GenerateSnapshot(clientConn, newCompactDB);

// 对使用快照初始化的SyncCompactDB3.sdf执行同步,因为快照中已经包含了服务器中的数据
// 所以本次同步将没有数据被同步,直到一方的数据发生变化
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();
syncOrchestrator.LocalProvider = new SqlCeSyncProvider("ProductsScope", clientConn);
syncOrchestrator.RemoteProvider = new SqlSyncProvider("ProductsScope", serverConn);
syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();
DisplayStats(syncStats);
}

static void DisplayStats(SyncOperationStatistics syncStats)
{
// 输出统计数据
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);
}

 

posted @ 2012-03-12 16:03  Life a Poem  阅读(4173)  评论(5编辑  收藏  举报