<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Life a Poem</title><subtitle type="text">Miracles sometimes occur, but one has to work terribly for them.</subtitle><id>http://feed.cnblogs.com/blog/u/99403/rss</id><updated>2012-05-08T09:36:35Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/99403/rss"/><entry><id>http://www.cnblogs.com/lifepoem/archive/2012/03/31/2426487.html</id><title type="text">Microsoft Sync Framework同步数据库 4：如何为数据库同步筛选数据</title><summary type="text">有时候，我们希望在同步作用域的基础上对同步的数据进行筛选，比如，按照销售人员同步订单数据。这个时候，我们就可以使用Sync Framework的筛选器机制来对同步数据进行筛选，以实现同步效率的提高或者满足特定的业务需求。Sync Framework 可以创建两种类型的筛选器：“静态筛选器”和“基于参数的筛选器”。</summary><published>2012-03-31T02:20:00Z</published><updated>2012-03-31T02:20:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2012/03/31/2426487.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2012/03/31/2426487.html"/><content type="html">&lt;p&gt;&lt;strong&gt;如何为数据库同步筛选数据&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;了解筛选器&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们知道，在为数据库准备同步时，我们需要定义同步作用域来描述同步的数据范围，它是对进行同步的对象的一种逻辑分组。对于数据库同步，一个同步作用域通常是一组数据表。但有时候，我们希望在同步作用域的基础上对同步的数据进行筛选，比如，按照销售人员同步订单数据。这个时候，我们就可以使用Sync Framework的筛选器机制来对同步数据进行筛选。&lt;/p&gt;&lt;p&gt;Sync Framework 可以创建两种类型的筛选器：&amp;ldquo;静态筛选器&amp;rdquo;和&amp;ldquo;基于参数的筛选器&amp;rdquo;。&lt;/p&gt;&lt;p&gt;静态筛选器定义为同步作用域的一部分，并且定义筛选字段的值。静态筛选器在源数据库使用的存储过程中进行编码，以便为作用域枚举变更。定义了某一静态筛选器后，就不能对其进行更改。在本篇的设置数据库一节中，我们已经定义了一个静态筛选器的完整示例。&lt;/p&gt;&lt;p&gt;基于参数的筛选器由一个筛选子句以及映射到同步作用域中表的列的一组参数定义。基于参数的筛选器在两个阶段中定义。第一个阶段定义筛选子句和参数，并且建立与该筛选器相关联的作用域的说明。在这个阶段中，筛选器和作用域仅采用模板格式。第二个阶段为筛选器设置参数值并且根据模板创建同步作用域。在此阶段中创建的作用域是目标提供程序用来与源数据库同步的作用域。用于基于参数的筛选的源数据库可以是 SQL Server 或 SQL Azure 数据库，目标数据库可以是 SQL Server、SQL Azure 或 SQL Server Compact 数据库。&lt;/p&gt;&lt;p&gt;在针对筛选的典型方案中，数据库管理员或应用程序开发人员定义基于参数的筛选器并且为筛选的同步准备服务器数据库。数据库管理员或应用程序开发人员还可以创建简单工具（例如基于 Web 的订阅工具），该工具使用 Sync Framework 对象以便让用户指定其筛选参数值并为同步订阅其客户端数据库。通过创建订阅工具，该数据库管理员不必为单独的用户创建筛选器，而是用户使用该工具指定适合自己的参数值，并且根据需要订阅同步。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;创建基于参数的筛选器&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;通过两个步骤创建基于参数的筛选器。首先，定义筛选器和作用域模板。然后，创建一个经过筛选的作用域，该作用域具有针对筛选器参数的特定值。这个由两个步骤构成的过程具有以下优势：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;易于设置。筛选器模板只需定义一次。&lt;/li&gt;&lt;li&gt;易于订阅。客户端指定要创建的参数值并且根据需要订阅经过筛选的作用域。&lt;/li&gt;&lt;li&gt;易于维护。即使在合并若干参数并且创建许多经过筛选的作用域时，维护工作也很简单，因为使用基于参数的单一过程来枚举变更。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;定义筛选器模板&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;创建基于参数的筛选器的第一个步骤是定义一个筛选器模板，以后可以使用该模板创建经过筛选的作用域。筛选器模板存储在源数据库中并且要求创建同步表和存储过程。因此，在源数据库中需要适当的权限。&lt;/p&gt;&lt;p&gt;筛选器模板与同步作用域一起定义。按如下所示为作用域中的表定义筛选器模板：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;通过使用 AddFilterColumn，向同步作用域中的 SqlSyncTableProvisioning 对象添加一个筛选器列。这会将该筛选器列添加到用于跟踪基表变更的跟踪表。&lt;/li&gt;&lt;li&gt;通过将 SqlParameter 对象添加到 SqlSyncTableProvisioning 对象的 FilterParameters 集合，定义一个或多个筛选参数。这会将指定的参数添加到在同步过程中枚举变更的存储过程的参数列表中。&lt;/li&gt;&lt;li&gt;添加一个筛选子句，该子句通过设置 SqlSyncTableProvisioning 对象的 FilterClause 属性，定义参数值和列值之间的关系。筛选子句是不带 WHERE 关键字的 WHERE 子句。[side] 别名是该跟踪表的别名。这些参数匹配在 FilterParameters 集合中指定的参数。此时，您只是定义筛选器参数和列之间的关系。以后在创建经过筛选的作用域时将指定参数的实际值。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;然后，通过使用 SqlSyncScopeProvisioning 对象的 Apply 方法将筛选器模板和作用域模板应用于源数据库，此时创建适当的同步表和存储过程。&lt;/p&gt;&lt;p&gt;在筛选子句中，别名 [base] 和 [side] 由 Sync Framework 定义。[base] 指代表的基名称，[side] 指代变更跟踪表。例如，基于 CustomerType 列筛选 Customer 表。默认情况下，[base] 是 [Customer] 的别名，[side] 是 [Customer_tracking] 的别名。由于 CustomerType 列在基表和跟踪表中都存在，在筛选子句中必须限定对它的引用，否则会引起歧义，出现错误。还可以使用实际表来替代 [base] 和 [side] 别名，如 [Customer_tracking].[CustomerType] = @customertype。&lt;/p&gt;&lt;p&gt;下面的示例定义一个筛选器模板并且将其应用于源数据库：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建同步作用域模板customertype_template，向其添加两个表&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt;             DbSyncScopeDescription scopeDesc = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DbSyncScopeDescription(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customertype_template&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 设置一个易于理解的注释&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt;             scopeDesc.UserComment = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Template for Customer and CustomerContact tables. Customer data is filtered by CustomerType parameter.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 定义作用域中的表&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt;             DbSyncTableDescription customerDescription = SqlSyncDescriptionBuilder.GetDescriptionForTable(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt;             scopeDesc.Tables.Add(customerDescription);&lt;br /&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt;             DbSyncTableDescription customerContactDescription = SqlSyncDescriptionBuilder.GetDescriptionForTable(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.CustomerContact&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;             scopeDesc.Tables.Add(customerContactDescription);&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建数据库设置对象以创建同步作用域模板&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;             SqlSyncScopeProvisioning serverTemplate = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(serverConn, scopeDesc, SqlSyncScopeProvisioningType.Template);&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;             serverTemplate.ObjectSchema = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 为Customer表指定用于过滤数据的列&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 为变更跟踪表设置过滤子句，[side]是变更跟踪表的别名&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 并且指定过滤参数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;             serverTemplate.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].AddFilterColumn(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;CustomerType&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;             serverTemplate.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].FilterClause = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[side].[CustomerType] = @customertype&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;             SqlParameter param = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlParameter(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;@customertype&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, SqlDbType.NVarChar, &lt;span style="color: #800080;"&gt;100&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;             serverTemplate.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].FilterParameters.Add(param);&lt;br /&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;             serverTemplate.Apply();&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;创建经过筛选的作用域&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在某一客户端可以使用筛选器与服务器同步前，该客户端必须首先为筛选器参数定义特定值。这个步骤将通过服务器上的筛选器模板来创建经过筛选的作用域，并将此筛选的作用域应用于服务器。&lt;/p&gt;&lt;p&gt;在对服务器数据库指定了经过筛选的作用域后，我们就可以通过调用 GetDescriptionForScope 以便获取该作用域，然后将该作用域应用于客户端数据库，对客户端数据库进行设置。&lt;/p&gt;&lt;p&gt;下面的示例为一个筛选器定义参数值，将该筛选器应用于服务器数据库，并且使用经过筛选的作用域设置客户端数据库以便准备进行同步：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 为retail customers创建同步作用域"RetailCustomers"，并且设置服务器数据库&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt;             SqlSyncScopeProvisioning serverProvRetail = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(serverConn);&lt;br /&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt;             serverProvRetail.ObjectSchema = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt;             serverProvRetail.PopulateFromTemplate(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RetailCustomers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customertype_template&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt;             serverProvRetail.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].FilterParameters[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;@customertype&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].Value = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Retail&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt;             serverProvRetail.UserComment = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Customer data includes only retail customers.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt;             serverProvRetail.Apply();&lt;br /&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 通过上面创建的同步作用域"RetailCustomers"来设置客户端数据库&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;             DbSyncScopeDescription clientSqlDesc = SqlSyncDescriptionBuilder.GetDescriptionForScope(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RetailCustomers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;             SqlSyncScopeProvisioning clientSqlConfig = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(clientSqlConn, clientSqlDesc);&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;             clientSqlConfig.ObjectSchema = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;             clientSqlConfig.Apply();&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;使用筛选作用域同步客户端&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在定义了经过筛选的作用域并且设置了客户端数据库后，可以通过在客户端和服务器数据库中为经过筛选的作用域创建 SqlSyncProvider 对象、将提供程序与 SyncOrchestrator 对象相关联和调用 Synchronize 方法，同步客户端。&lt;/p&gt;&lt;p&gt;下面的示例执行两个数据库的筛选同步：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt;             SyncOrchestrator syncOrchestrator = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SyncOrchestrator();&lt;br /&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt;             syncOrchestrator.LocalProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncProvider(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RetailCustomers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, clientSqlConn, &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt;             syncOrchestrator.RemoteProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncProvider(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RetailCustomers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn, &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt;             SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;订阅同步&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;从上面的介绍中我们可以看到，使用同步作用域模板来同步某一客户端数据库的过程包括：定义筛选器参数值、创建筛选器作用域并应用于服务器数据库以及设置客户端数据库。试想，如果我们需要为每个不同的参数值来创建筛选器作用域、设置服务器数据库、设置客户端数据库，那将会一件非常无聊而繁重的任务。当然，我们可以想出相应的解决方案，来让这些步骤自动化，这个解决方案就是创建同步订阅服务。&lt;/p&gt;&lt;p&gt;用于定义筛选器参数值、将新指定的筛选器应用于服务器数据库以及设置客户端数据库的代码可以轻松地封装在单独的工具中，该工具收集来自某一用户的筛选器参数值并且为筛选的同步订阅该用户的客户端数据库。请参阅下面的步骤来完成一个简单的同步订阅服务：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;准备数据库&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;请参阅&amp;ldquo;同步数据库示例：同步 SQL Server 和 SQL Server Compact&amp;rdquo; 一篇的&amp;ldquo;创建示例服务器数据库&amp;rdquo;一节来创建SyncDB数据库&lt;/p&gt;&lt;p&gt;&lt;strong&gt;定义筛选器模板&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;运行下面的程序来定义一个筛选器模板&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt;         &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 测试同步订阅之前，请使用此方法先在服务器数据库中创建同步作用域模板&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; CreateSyncTemplateOnServer()&lt;br /&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt;         {&lt;br /&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; ServerConnectionString = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source=localhost; Initial Catalog=SyncDB; Integrated Security=True&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; serverConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlConnection(ServerConnectionString))&lt;br /&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt;             {&lt;br /&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;定义筛选同步作用域OrdersScope-NC &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt;                 DbSyncScopeDescription scopeDesc = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DbSyncScopeDescription(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OrdersScope_Template&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;从SyncDB 服务器数据库检索Orders表的架构并添加至同步作用域&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;                 DbSyncTableDescription tableDesc = SqlSyncDescriptionBuilder.GetDescriptionForTable(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;                 scopeDesc.Tables.Add(tableDesc);&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建一个同步设置对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;                 SqlSyncScopeProvisioning serverProvision = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(serverConn, scopeDesc, SqlSyncScopeProvisioningType.Template);&lt;br /&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;                 serverProvision.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].AddFilterColumn(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OriginState&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;                 serverProvision.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].FilterClause = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[side].[OriginState] = @originState&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;                 SqlParameter param = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlParameter(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;@originState&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, SqlDbType.NVarChar, &lt;span style="color: #800080;"&gt;2&lt;/span&gt;);&lt;br /&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;                 serverProvision.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].FilterParameters.Add(param);&lt;br /&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 开始设置过程&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;                 serverProvision.Apply();&lt;br /&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;             }&lt;br /&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;         }&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;创建同步订阅服务&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;新建一个WCF Service Application，创建的订阅服务如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt;         &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; Subscribe Sync Scope for Client&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; Create Sync Scope from Sync Scope Template, then Provision the server database, then Provision the client database.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;param name="ScopeTemplateName"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;param name="SyncObjectSchema"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;param name="FilterParameters"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #808080;"&gt;///&lt;/span&gt; &lt;span style="color: #808080;"&gt;&amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; SubscribeSyncScopeForClient(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; ScopeTemplateName, &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; SyncObjectSchema, List&amp;lt;SyncScopeParameter&amp;gt; FilterParameters, &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; clientConnectionString)&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;         {&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;1. 生成客户端ScopeName, 依据传入的Scope Template Name外加Guid生成，确保唯一性&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;             Guid clientId = Guid.NewGuid();&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; _clientScopeName = String.Format(CultureInfo.InvariantCulture, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;{0}_{1}&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, ScopeTemplateName, clientId);&lt;br /&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;2. 设置服务器端数据库&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;2.1 设置服务器端连接字符串，本例中将对SyncDB数据库进行设置&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; ServerConnectionString = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source=localhost; Initial Catalog=SyncDB; Integrated Security=True&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; serverConnection = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlConnection(ServerConnectionString))&lt;br /&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt;             {&lt;br /&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; provisioning = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(serverConnection);&lt;br /&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;如果需要设置同步架构名称&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(SyncObjectSchema))&lt;br /&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt;                 {&lt;br /&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt;                     provisioning.ObjectSchema = SyncObjectSchema;&lt;br /&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt;                 }&lt;br /&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;判断传入的ScopeName是否是同步作用域模板&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!provisioning.TemplateExists(ScopeTemplateName))&lt;br /&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt;                 {&lt;br /&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Exception(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;No scope temple '{0}' found in server database.&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, ScopeTemplateName));&lt;br /&gt;&lt;span style="color: #008080;"&gt;32&lt;/span&gt;                 }&lt;br /&gt;&lt;span style="color: #008080;"&gt;33&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;34&lt;/span&gt;                 provisioning.PopulateFromTemplate(_clientScopeName, ScopeTemplateName);&lt;br /&gt;&lt;span style="color: #008080;"&gt;35&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;处理过滤参数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;36&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; != FilterParameters &amp;amp;&amp;amp; &lt;span style="color: #800080;"&gt;0&lt;/span&gt; != FilterParameters.Count)&lt;br /&gt;&lt;span style="color: #008080;"&gt;37&lt;/span&gt;                 {&lt;br /&gt;&lt;span style="color: #008080;"&gt;38&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; param &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; FilterParameters)&lt;br /&gt;&lt;span style="color: #008080;"&gt;39&lt;/span&gt;                     {&lt;br /&gt;&lt;span style="color: #008080;"&gt;40&lt;/span&gt;                         provisioning.Tables[param.TableName].FilterParameters[param.ParameterName].Value = param.ParameterValue;&lt;br /&gt;&lt;span style="color: #008080;"&gt;41&lt;/span&gt;                     }&lt;br /&gt;&lt;span style="color: #008080;"&gt;42&lt;/span&gt;                 }&lt;br /&gt;&lt;span style="color: #008080;"&gt;43&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;同步服务器 &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;44&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!provisioning.ScopeExists(_clientScopeName))&lt;br /&gt;&lt;span style="color: #008080;"&gt;45&lt;/span&gt;                 {&lt;br /&gt;&lt;span style="color: #008080;"&gt;46&lt;/span&gt;                     provisioning.Apply();&lt;br /&gt;&lt;span style="color: #008080;"&gt;47&lt;/span&gt;                 }&lt;br /&gt;&lt;span style="color: #008080;"&gt;48&lt;/span&gt;                 &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;设置客户端数据库，此处假设客户端数据库类型为Sql Server数据库&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;49&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; clientConnection = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlConnection(clientConnectionString))&lt;br /&gt;&lt;span style="color: #008080;"&gt;50&lt;/span&gt;                 {&lt;br /&gt;&lt;span style="color: #008080;"&gt;51&lt;/span&gt;                     DbSyncScopeDescription scopeDesc = SqlSyncDescriptionBuilder.GetDescriptionForScope(_clientScopeName, serverConnection);&lt;br /&gt;&lt;span style="color: #008080;"&gt;52&lt;/span&gt;                     SqlSyncScopeProvisioning clientProvision = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(clientConnection, scopeDesc);&lt;br /&gt;&lt;span style="color: #008080;"&gt;53&lt;/span&gt;                     clientProvision.Apply();&lt;br /&gt;&lt;span style="color: #008080;"&gt;54&lt;/span&gt;                 }&lt;br /&gt;&lt;span style="color: #008080;"&gt;55&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; _clientScopeName; &lt;br /&gt;&lt;span style="color: #008080;"&gt;56&lt;/span&gt;             }&lt;br /&gt;&lt;span style="color: #008080;"&gt;57&lt;/span&gt;         }&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;调用同步订阅服务&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;新建一个Console Application客户端程序来测试该同步订阅服务，关键代码如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt;         {&lt;br /&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;准备服务参数&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; scopeTemplateName = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OrdersScope_Template&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt;             List&amp;lt;ServiceReference1.SyncScopeParameter&amp;gt; list = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;ServiceReference1.SyncScopeParameter&amp;gt;();&lt;br /&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt;             list.Add(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ServiceReference1.SyncScopeParameter() { TableName = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, ParameterName = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;@originState&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, ParameterValue = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;WA&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; });&lt;br /&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; clientConnectionString = &lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source=localhost; Initial Catalog=SyncDB2; Integrated Security=True&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt;             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;调用同步订阅服务&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; clientScopeName = (&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; ServiceReference1.DatabaseSyncSubscriberClient())&lt;br /&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;                 .SubscribeSyncScopeForClient(scopeTemplateName, &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;, list.ToArray(), clientConnectionString);&lt;br /&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;             Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Both server and client databases are provisioned for scope {0}&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, clientScopeName);&lt;br /&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;         }&lt;/div&gt;&lt;p&gt;完整的项目源代码请&lt;a title="点击这里下载项目源码" href="http://files.cnblogs.com/lifepoem/SynchronizationSubscriber.zip"&gt;点击这里&lt;/a&gt;下载。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2426487.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/31/2426487.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2012/03/12/2391945.html</id><title type="text">Microsoft Sync Framework同步数据库 3：针对同步进行设置</title><summary type="text">在可以使用 Sync Framework 同步数据库之前，需要通过称为“设置（provisioning）”的流程配置它。所需的设置类型因数据库类型而异。本篇提供有关设置 SQL Server 和 SQL Server Compact 数据库的背景信息、操作步骤以及完整代码示例。</summary><published>2012-03-12T08:03:00Z</published><updated>2012-03-12T08:03:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2012/03/12/2391945.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2012/03/12/2391945.html"/><content type="html">&lt;p&gt;&lt;strong&gt;针对同步进行设置&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在可以使用 Sync Framework 同步数据库之前，需要通过称为&amp;ldquo;设置（provisioning）&amp;rdquo;的流程配置它。所需的设置类型因数据库类型而异。本篇提供有关设置 SQL Server 和 SQL Server Compact 数据库的背景信息、操作步骤以及完整代码示例。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;了解设置和取消设置(Provision and Deprovision)&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;为同步配置数据库的第一步是定义一个作用域，该作用域标识要同步的内容。在您定义同步作用域后，就可以使用该同步作用域来设置数据库，以便创建变更跟踪和元数据管理基础结构，该基础结构由元数据表、触发器和存储过程构成。在设置了某一数据库后，可以通过使用某一提供程序（例如 SqlSyncProvider）来表示该数据库和使用 SyncOrchestrator 对象管理同步会话并连接到其他同步提供程序以实现数据同步。为同步设置数据库是有别于与其他数据库同步的单独任务，这部分代码通常位于单独的应用程序中。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;设置(Provision)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在设置(Provision)数据库时，通常会在数据库中创建以下某些或全部元素：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;在同步作用域中包含的基表。&lt;/li&gt;&lt;li&gt;作用域中每个基表的一个跟踪表。该跟踪表跟踪对关联基表进行的变更。&lt;/li&gt;&lt;li&gt;在直接对基表进行更改时更新跟踪表的触发器。&lt;/li&gt;&lt;li&gt;用于同步操作的存储过程，例如枚举变更、插入变更、更新数据或删除数据。通过设置对象的SetUseBulkProceduresDefault方法可以为SQL Server 2008 和 SQL Azure 数据库创建使用表值函数一次执行多行的插入、更新和删除操作的成批过程。&lt;/li&gt;&lt;li&gt;包含同步作用域信息的特殊表，例如 scope_info 表。如果这些表尚不存在，则创建这些表。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;数据库设置对象提供了相应方法来控制上面这些同步元素的创建，比如：基表创建由 SetCreateTableDefault 方法控制，跟踪表创建由 SetCreateTrackingTableDefault 方法控制。此外，同步元素可以创建在数据库的单独架构（Schema）中，这是通过 SqlSyncScopeProvisioning类的ObjectSchema 属性实现的。&lt;/p&gt;&lt;p&gt;可通过调用 SqlSyncScopeProvisioning.Apply 或 SqlCeSyncScopeProvisioning.Apply方法直接应用设置；或者，对于 SQL Server 数据库，可以创建一个脚本并在以后运行该脚本来设置数据库。若要创建设置脚本，请调用 SqlSyncScopeProvisioning.Script 方法。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;取消设置(Deprovision)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果您不再需要某一作用域，则可以通过调用SqlSyncScopeDeprovisioning.DeprovisionScope 或 SqlCeSyncScopeDeprovisioning.DeprovisionScope，删除该作用域及其关联的元数据表、触发器和存储过程。在已删除某一作用域后，该作用域不再用于同步。如果某一数据库元素（例如元数据表）由多个作用域使用，则在使用该元素的最后一个作用域被删除前，将不删除该元素。例如，您具有名为 Customers 的一个表，并且定义两个分别名为 RetailCustomers 和 WholesaleCustomers 的作用域，并且这两个作用域包含 Customers 表。在您删除 WholesaleCustomers 作用域时，用于 Customers 表的元数据表不删除，因为它仍由 RetailCustomers 作用域使用。&lt;/p&gt;&lt;p&gt;如果您使用基于参数的筛选器来筛选 SQL Server 或 SQL Azure 数据库中的同步数据，则首先创建一个筛选器模板，然后基于该筛选器模板创建筛选的作用域。您还可以通过调用 DeprovisionTemplate，轻松地删除该筛选器模板和基于该模板创建的所有经过筛选的作用域，以及所有关联的元数据表、触发器和存储过程。例如，您创建一个 customerstate_template 模板，该模板通过使用 state 参数进行筛选。您基于 customerstate_template 创建两个经过筛选的作用域 customers_WA 和 customers_OR。在您删除 customerstate_template 时，customers_WA 和 customers_OR 也删除。&lt;/p&gt;&lt;p&gt;您还可以通过调用SqlSyncScopeDeprovisioning.DeprovisionStore 或 SqlCeSyncScopeDeprovisioning.DeprovisionStore，从数据库中删除所有作用域和筛选器以及所有同步元数据表、触发器和存储过程。此外，因为删除单独的作用域和筛选器模板将仅删除作用域级别和模板级别的元数据，而不删除数据库级别的元数据，所以，SqlSyncScopeDeprovisioning.DeprovisionStore 或 SqlCeSyncScopeDeprovisioning.DeprovisionStore 可用于在删除了所有作用域和模板后清除剩余的同步元数据表。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;设置数据库&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步作用域和同步模板&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们之前已经了解到，同步作用域是对进行同步的对象的一种逻辑分组。对于数据库同步，一个同步组通常是一组数据表，并且数据表可以被过滤。同时一个数据表可以被包含在一个或多个同步组中。&lt;/p&gt;&lt;p&gt;有些时候，我们需要使用基于参数的筛选器来筛选 SQL Server 或 SQL Azure 数据库中的同步数据，则首先创建一个筛选器模板，然后基于该筛选器模板创建筛选的作用域。比如，每个销售人员只对自己相关的订单数据感兴趣，那么我们就需要针对每个销售人员创建同步作用域，这时，我们就可以使用同步模板来简化同步作用域的创建过程，甚至通过订阅的手段来实现这一过程的自动化。关于筛选器模板的详细介绍请参考下篇&amp;ldquo;如何为数据库同步筛选数据&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;定义同步作用域&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下面的代码定义了一个名为filtered_customer 的同步作用域，并为其添加了两个表：Customer和CustomerContact。因为这些表已经存在于服务器数据库之中，所以使用GetDescriptionForTable方法来检索表的架构。Customer表的所有列都包含在同步作用域中，但是CustomerContact表只包含了两列。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            DbSyncScopeDescription scopeDesc = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DbSyncScopeDescription(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;filtered_customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Definition for Customer.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            DbSyncTableDescription customerDescription =&lt;br /&gt;                SqlSyncDescriptionBuilder.GetDescriptionForTable(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;br /&gt;            scopeDesc.Tables.Add(customerDescription);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Definition for CustomerContact, including the list of columns to include.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            Collection&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; columnsToInclude = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Collection&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;            columnsToInclude.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;CustomerId&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            columnsToInclude.Add(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;PhoneType&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            DbSyncTableDescription customerContactDescription =&lt;br /&gt;                SqlSyncDescriptionBuilder.GetDescriptionForTable(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.CustomerContact&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, columnsToInclude, serverConn);&lt;br /&gt;&lt;br /&gt;            scopeDesc.Tables.Add(customerContactDescription);&lt;/div&gt;&lt;p&gt;&lt;strong&gt;设置服务器数据库&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下面的代码为filtered_customer 同步作用域创建了一个设置对象，并且指定所有同步元素创建在"Sync"数据库架构中。代码还为Customer表指定了一个过滤条件，只有满足该条件的数据行才会被同步。定义一个过滤条件分为两部分：调用AddFilterColumn指定过滤列名为&amp;rdquo;CustomerType&amp;rdquo;，它会被添加到变更跟踪表以跟踪Customer表的改变。调用FilterClause指定过滤条件本身，它是不包含WHERE关键字的WHERE子句。[side]是变更跟踪表的别名。定义好设置选项后，Apply方法会在服务器数据库中创建变更跟踪基础结构，并且把设置脚本写到一个文件中。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            SqlSyncScopeProvisioning serverConfig = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(serverConn, scopeDesc);&lt;br /&gt;            serverConfig.ObjectSchema = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Specify which column(s) in the Customer table to use for filtering data, &lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; and the filtering clause to use against the tracking table.&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; "[side]" is an alias for the tracking table.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            serverConfig.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].AddFilterColumn(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;CustomerType&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            serverConfig.Tables[&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sales.Customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;].FilterClause = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;[side].[CustomerType] = 'Retail'&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Configure the scope and change-tracking infrastructure.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            serverConfig.Apply();&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Write the configuration script to a file. You can modify &lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; this script if necessary and run it against the server&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; to customize behavior.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            File.WriteAllText(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;SampleConfigScript.txt&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConfig.Script());&lt;/div&gt;&lt;p&gt;&lt;strong&gt;设置客户端数据库&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们可以通过两种方式来设置客户端数据库：&lt;/p&gt;&lt;p&gt;1． 基于从服务器或另外的客户端数据库获取的scope/作用域信息，完全初始化一个SQL Server或SQL Server Compact客户端数据库。我们可以通过SqlSyncDescriptionBuilder和SqlCeSyncDescriptionBuilder对象来获取同步作用域的架构信息，从而在客户端数据库创建同步对象。&lt;/p&gt;&lt;p&gt;2． 通过一个已经存在的客户端数据库来对一个SQL Server Compact客户端数据库进行快照初始化。&lt;/p&gt;&lt;p&gt;快照初始化的主要目的是减少初始化客户端数据库所需的时间。更多关于快照初始化的知识请参照本篇&amp;ldquo;使用快照设置数据库&amp;rdquo;的详细介绍。&lt;/p&gt;&lt;p&gt;下面的代码示例首先从服务器获取同步作用域信息，并使用它们来设置一个SQL Server Compact客户端数据库。然后，基于该SQL Server Compact客户端数据库的作用域信息来设置另一个SQL Server客户端数据库。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建一个SQL Server Compact数据库并用从服务器端获取的作用域信息来设置它&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Compact数据库不支持单独的schema，&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 所以我们通过为所有的同步对象增加前缀"Sync"来使他们易于区分&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync1, &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;);&lt;br /&gt;            Utility.DeleteAndRecreateCompactDatabase(Utility.ConnStr_SqlCeSync2, &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;);&lt;br /&gt;            DbSyncScopeDescription clientSqlCe1Desc = SqlSyncDescriptionBuilder.GetDescriptionForScope(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;filtered_customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;            SqlCeSyncScopeProvisioning clientSqlCe1Config = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeSyncScopeProvisioning(clientSqlCe1Conn, clientSqlCe1Desc);&lt;br /&gt;            clientSqlCe1Config.ObjectPrefix = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;            clientSqlCe1Config.Apply();&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 通过从SQL Server Compact数据库中获取的同步作用域信息来设置一个SQL Server客户端数据库&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 当然我们也可以从服务器端获取作用域信息&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            DbSyncScopeDescription clientSqlDesc = SqlCeSyncDescriptionBuilder.GetDescriptionForScope(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;filtered_customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, clientSqlCe1Conn);&lt;br /&gt;            SqlSyncScopeProvisioning clientSqlConfig = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(clientSqlConn, clientSqlDesc);&lt;br /&gt;            clientSqlConfig.ObjectSchema = &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sync&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;            clientSqlConfig.Apply();&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;取消设置数据库&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下面的代码示例为我们展示了如何：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;在客户端数据库中取消设置一个同步作用域&lt;/li&gt;&lt;li&gt;在服务器数据库中取消设置筛选器模板和相关的作用域&lt;/li&gt;&lt;li&gt;完全取消设置一个客户端数据库，这样所有的同步对象都会被删除&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;删除一个作用域&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下面的示例在一个SQL Server客户端数据库中删除RetailCustomers作用域。同时，删除作用域的脚本被保存到了一个文件之中，这个脚本可以用来执行以删除其他数据库中的RetailCustomers作用域。淡然，这个步骤对于删除一个同步作用域来说是可选的。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在SQL Server客户端数据库中删除RetailCustomers作用域&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlSyncScopeDeprovisioning clientSqlDepro = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeDeprovisioning(clientSqlConn);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 首先把取消设置的SQL脚本保存下来，以便取消设置其他的SQL Server客户端数据库&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 这一步是可选的&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            File.WriteAllText(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;SampleDeprovisionScript.txt&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                clientSqlDepro.ScriptDeprovisionScope(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RetailCustomers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;));&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 删除作用域&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            clientSqlDepro.DeprovisionScope(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;RetailCustomers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;/div&gt;&lt;p&gt;&lt;strong&gt;删除一个筛选器模板&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在删除一个筛选器模板之前，我们通常需要查看从这个筛选器模板创建出来的同步作用域，因为当这个筛选器模板被删除（Deprovision）时，所有这些作用域也会被删除。下面的SQL脚本可以用来查找由customertype_template筛选器模板所创建的筛选作用域。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #008080;"&gt;--&lt;/span&gt;&lt;span style="color: #008080;"&gt; Find all filtered scopes that were created from the filtered scope template named 'customertype_template'.&lt;/span&gt;&lt;span style="color: #008080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; sync_scope_name &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; scope_info &lt;br /&gt;      &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; scope_config_id &lt;span style="color: #808080;"&gt;=&lt;/span&gt; &lt;br /&gt;      (&lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; template_config_id &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; scope_templates &lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; template_name &lt;span style="color: #808080;"&gt;=&lt;/span&gt; N&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;customertype_template&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;)&lt;/div&gt;&lt;p&gt;下面的示例从SQL Server服务器数据库中删除customertype_template筛选器模板。在删除该模板的同时也会删除由它创建出来的作用域RetailCustomers和WholesaleCustomers。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 从服务器数据库中删除"customertype_template"模板&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 这样也会删除所有依赖与该模板的作用域&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlSyncScopeDeprovisioning serverSqlDepro = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeDeprovisioning(serverConn);&lt;br /&gt;            serverSqlDepro.DeprovisionTemplate(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customertype_template&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;/div&gt;&lt;p&gt;&lt;strong&gt;删除所有同步对象&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下面的示例从一个SQL Server Compact客户端数据库中删除所有的同步对象，包括：同步元数据表、触发器和存储过程。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在SQL Server Compact数据库这哦你删除所有的同步对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlCeSyncScopeDeprovisioning clientSqlCeDepro = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeSyncScopeDeprovisioning(clientSqlCe1Conn);&lt;br /&gt;            clientSqlCeDepro.DeprovisionStore();&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;使用快照设置数据库&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果我们需要对多个SQL Server Compact数据库的同步进行设置，那么我们可以使用数据库快照来减少初始化所需的时间。一个快照是特别准备的，包含了表架构、数据（可选）、和变更跟踪基础结构的SQL Server Compact数据库。在我们对一个SQL Server Compact数据库作完全初始化后，我们可以为其创建一个快照，该快照可以拷贝至其他需要同步的SQL Server Compact数据库。对数据库应用快照的过程比完全初始化要高效得多。&lt;/p&gt;&lt;p&gt;下面的示例为我们展示了通过从服务器数据库获取的作用域信息来设置Compact数据库，然后使用该数据库的快照来初始化另外一个数据库。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; SynchronizationUsingSnapshot()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 通过从服务器数据库获取的作用域信息来设置Compact数据库SyncCompactDB2.sdf&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlCeConnection clientConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeConnection(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source='D:\Sync Framework\CompactDB\SyncCompactDB2.sdf'&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            SqlConnection serverConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlConnection(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source=localhost; Initial Catalog=SyncDB; Integrated Security=True&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            DbSyncScopeDescription scopeDesc = SqlSyncDescriptionBuilder.GetDescriptionForScope(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductsScope&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;            SqlCeSyncScopeProvisioning clientProvision = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeSyncScopeProvisioning(clientConn, scopeDesc);&lt;br /&gt;            clientProvision.Apply();&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 从SQL Server Compact数据库创建一个快照，该快照将用于初始化其他的Compact数据库&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 尽管我们可以从其他数据库获取作用域信息来初始化，但快照的使用为Compact数据库提供了一个更加快捷方便的部署方案。&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; SyncCompactDB3.sdf为不存在的Compact数据库，将在GenerateSnapshot方法中自动创建&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; newCompactDB = &lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;D:\Sync Framework\CompactDB\SyncCompactDB3.sdf&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;;&lt;br /&gt;            SqlCeSyncStoreSnapshotInitialization syncStoreSnapshot = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeSyncStoreSnapshotInitialization();&lt;br /&gt;            syncStoreSnapshot.GenerateSnapshot(clientConn, newCompactDB);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 对使用快照初始化的SyncCompactDB3.sdf执行同步,因为快照中已经包含了服务器中的数据&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 所以本次同步将没有数据被同步，直到一方的数据发生变化&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SyncOrchestrator syncOrchestrator = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SyncOrchestrator();&lt;br /&gt;            syncOrchestrator.LocalProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeSyncProvider(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductsScope&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, clientConn);&lt;br /&gt;            syncOrchestrator.RemoteProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncProvider(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductsScope&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;            syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;&lt;br /&gt;            SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();&lt;br /&gt;            DisplayStats(syncStats);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; DisplayStats(SyncOperationStatistics syncStats)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 输出统计数据&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Start Time: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.SyncStartTime);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Total Changes Uploaded: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.UploadChangesTotal);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Total Changes Downloaded: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.DownloadChangesTotal);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Complete Time: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.SyncEndTime);&lt;br /&gt;            Console.WriteLine(String.Empty);&lt;br /&gt;        }&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2391945.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/12/2391945.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387497.html</id><title type="text">Microsoft Sync Framework同步数据库 2：同步SQL Server和SQL Server Compact示例</title><summary type="text">本篇文章通过使用 Sync Framework同步数据库的一个完整示例讲述了 执行常见同步任务的操作步骤。该示例旨在说明如何通过使用 Sync Framework 同步 SQL Server 数据库（包括 SQL Server Express 和 SQL Server Compact）。</summary><published>2012-03-09T05:44:00Z</published><updated>2012-03-09T05:44:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387497.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387497.html"/><content type="html">&lt;p&gt;&lt;strong&gt;同步SQL Server和SQL Server Compact示例&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本篇文章通过使用 Sync Framework同步数据库的一个完整示例讲述了 执行常见同步任务的操作步骤。该示例旨在说明如何通过使用 Sync Framework 同步 SQL Server 数据库（包括 SQL Server Express 和 SQL Server Compact）。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;创建示例服务器数据库&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这里，我们将创建一个示例 SQL Server 数据库，以后在同步应用场景中将会使用该数据库。下面是创建该数据库的详细步骤：&lt;/p&gt;&lt;p&gt;1．启动SQL Server Management Studio（SSMS），连接到SQL Server服务器。&lt;/p&gt;&lt;p&gt;2．新建一个查询，输入并运行一下SQL脚本：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;USE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;master&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;IF&lt;/span&gt; &lt;span style="color: #808080;"&gt;EXISTS&lt;/span&gt;(&lt;span style="color: #0000ff;"&gt;SELECT&lt;/span&gt; name &lt;span style="color: #0000ff;"&gt;FROM&lt;/span&gt; sys.databases &lt;span style="color: #0000ff;"&gt;WHERE&lt;/span&gt; name &lt;span style="color: #808080;"&gt;=&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;SyncDB&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;) &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;DROP&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;DATABASE&lt;/span&gt; SyncDB&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;CREATE&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;DATABASE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;SyncDB&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;USE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;SyncDB&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;CREATE&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TABLE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Products&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;(&lt;br /&gt;    &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;int&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;    &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;nvarchar&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;(&lt;span style="color: #800000; font-weight: bold;"&gt;50&lt;/span&gt;) &lt;span style="color: #808080;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;    &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ListPrice&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;money&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;CONSTRAINT&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;PK_Products&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;KEY&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CLUSTERED&lt;/span&gt; (&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;ASC&lt;/span&gt;) &lt;br /&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;CREATE&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TABLE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;( &lt;br /&gt;    &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;OrderID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;int&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;    &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ProductID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;int&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;    &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Quantity&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;int&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #808080;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;    &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;OriginState&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;nvarchar&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;(&lt;span style="color: #800000; font-weight: bold;"&gt;2&lt;/span&gt;) &lt;span style="color: #808080;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;, &lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;CONSTRAINT&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;PK_Orders&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;PRIMARY&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;KEY&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CLUSTERED&lt;/span&gt; (&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;OrderID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;ASC&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ProductID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;ASC&lt;/span&gt;) &lt;br /&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;ALTER&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TABLE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;  &lt;span style="color: #0000ff;"&gt;WITH&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CHECK&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;ADD&lt;/span&gt;  &lt;span style="color: #0000ff;"&gt;CONSTRAINT&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;FK_Orders_Products&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;FOREIGN&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;KEY&lt;/span&gt;(&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ProductID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;REFERENCES&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Products&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; (&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ID&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;ALTER&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TABLE&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;dbo&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt;.&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Orders&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CHECK&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CONSTRAINT&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;FK_Orders_Products&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;]&lt;/span&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;GO&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Products &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;1&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;PC&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;400&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Products &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;2&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Laptop&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;600&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Products &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;3&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;NetBook&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;300&lt;/span&gt;) &lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Orders &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;1&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;1&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;2&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;NC&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Orders &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;2&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;2&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;1&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;NC&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Orders &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;3&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;1&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;5&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;WA&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Orders &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;3&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;3&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;10&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;WA&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;) &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;INSERT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;INTO&lt;/span&gt; Orders &lt;span style="color: #0000ff;"&gt;VALUES&lt;/span&gt; (&lt;span style="color: #800000; font-weight: bold;"&gt;4&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;2&lt;/span&gt;, &lt;span style="color: #800000; font-weight: bold;"&gt;4&lt;/span&gt;, &lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;WA&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'&lt;/span&gt;)&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;定义作用域和设置服务器&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;为使服务器数据库做好同步准备，您将需要描述同步作用域并使用与作用域相关的项目来设置服务器数据库。&lt;/p&gt;&lt;p&gt;通过描述同步作用域来定义要同步的内容。同步作用域是必须作为一个单元来同步的一组表。同步作用域中的表可以已存在于数据库中；也可以通过使用 Sync Framework 对象模型描述这些表，然后在设置基础存储区时在运行时生成它们。这里我们将使用服务器数据库中已存在的 Products 表。&lt;/p&gt;&lt;p&gt;数据库设置涉及将与同步作用域相关的项目（例如跟踪表、触发器和存储过程）添加到数据库。这些项目由同步过程在运行时使用。在这个演练中，我们将创建一个控制台应用程序，该应用程序定义名为 ProductsScope 的同步作用域（包括 Products 表），并且使用与同步作用域相关的项目设置在上一步中创建的 SQL Server 数据库。&lt;/p&gt;&lt;p&gt;1． 打开Visual Studio 2008/2010，新建一个控制台应用程序ProvisionServer。并为&amp;ldquo;解决方案名称&amp;rdquo;键入 SyncSQLServerAndSQLCompact。&lt;/p&gt;&lt;p&gt;2． 添加对Microsoft.Synchronization.Data 和 Microsoft.Synchronization.Data.SqlServer程序集的引用。&lt;/p&gt;&lt;p&gt;3． 按下面的代码完成该控制台应用程序：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Data.SqlClient;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data.SqlServer;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt; ProvisionServer&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建数据库连接&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlConnection serverConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlConnection(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source=localhost; Initial Catalog=SyncDB; Integrated Security=True&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;定义同步作用域ProductsScope&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            DbSyncScopeDescription scopeDesc = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DbSyncScopeDescription(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductsScope&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;从SyncDB 服务器数据库检索Products表的架构&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            DbSyncTableDescription tableDesc = SqlSyncDescriptionBuilder.GetDescriptionForTable(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Products&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;向同步作用域中添加同步表的描述&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            scopeDesc.Tables.Add(tableDesc);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建一个同步作用域设置对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlSyncScopeProvisioning serverProvision = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncScopeProvisioning(serverConn, scopeDesc);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;如果表已经存在则略过创建表的步骤&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            serverProvision.SetCreateTableDefault(DbSyncCreationOption.Skip);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;开始设置过程&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            serverProvision.Apply();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;4． 运行该控制台程序。&lt;/p&gt;&lt;p&gt;5． 在SQL Server Management Studio中，依次展开 SyncDB 节点和&amp;ldquo;表&amp;rdquo;，此时您应会看到设置过程创建的以下附加表：Products_Tracking、schema_info、scope_config 和 scope_info。还有设置过程创建的其他数据库对象，例如触发器和存储过程。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;设置 SQL Compact 客户端&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在，我们将创建一个名为 SyncCompactDB 的 SQL Server Compact 数据库，并且创建一个控制台应用程序，该应用程序使用与 ProductsScope 相关的项目设置该Compact数据库。设置过程将使客户端数据库做好与服务器进行同步的准备。在前一步骤：定义作用域和设置服务器中，您已使用与同步相关的项目设置了服务器数据库。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;创建 SQL Server Compact &lt;/strong&gt;&lt;strong&gt;数据库&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;1． 在SQL Server Management Studio 中，单击&amp;ldquo;文件&amp;rdquo;菜单，然后单击&amp;ldquo;连接对象资源管理器&amp;rdquo;。&lt;/p&gt;&lt;p&gt;2． 在&amp;ldquo;连接到服务器&amp;rdquo;对话框中，为&amp;ldquo;服务器类型&amp;rdquo;选择 SQL Server Compact Edition。&lt;/p&gt;&lt;p&gt;3． 单击&amp;ldquo;数据库文件&amp;rdquo;旁边的向下箭头，然后单击&amp;ldquo;新建数据库&amp;rdquo;。&lt;/p&gt;&lt;p&gt;4． 在&amp;ldquo;创建新的 SQL Server Compact 数据库&amp;rdquo;对话框中，为&amp;ldquo;数据库文件名&amp;rdquo;键入 C:\SyncSQLServerAndSQLCompact\SyncCompactDB.sdf，然后单击&amp;ldquo;确定&amp;rdquo;。&lt;/p&gt;&lt;p&gt;5． 在您看到的关于空密码的消息框上单击&amp;ldquo;是&amp;rdquo;。&lt;/p&gt;&lt;p&gt;6． 在&amp;ldquo;连接到服务器&amp;rdquo;对话框中单击&amp;ldquo;连接&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;设置 SQL Server Compact &lt;/strong&gt;&lt;strong&gt;数据库&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;1． 在上一步骤中创建的SyncSQLServerAndSQLCompact解决方案中添加一个新的控制台应用程序ProvisionClient。&lt;/p&gt;&lt;p&gt;2． 添加对Microsoft.Synchronization、Microsoft.Synchornization.Data、Microsoft.Synchronization.Data.SqlServer、Microsoft.Synchronization.Data.SqlServerCe程序集的引用。&lt;/p&gt;&lt;p&gt;3． 添加对 System.Data.SqlServerCe 程序集的引用。&lt;/p&gt;&lt;p&gt;4． 按下面的代码完成该控制台应用程序：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Data.SqlClient;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Data.SqlServerCe;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data.SqlServer;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data.SqlServerCe;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt; ProvisionClient&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建到SyncCompactDB数据库的连接&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlCeConnection clientConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeConnection(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source='D:\Sync Framework\CompactDB\SyncCompactDB.sdf'&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建到SyncDB服务器数据库的连接&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlConnection serverConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlConnection(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source=localhost; Initial Catalog=SyncDB; Integrated Security=True&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;从SyncDB服务器数据库中获取ProductsScope同步作用域&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            DbSyncScopeDescription scopeDesc = SqlSyncDescriptionBuilder.GetDescriptionForScope(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductsScope&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;基于ProductsScope同步作用域创建CE设置对象&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlCeSyncScopeProvisioning clientProvision = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeSyncScopeProvisioning(clientConn, scopeDesc);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;开始设置过程&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            clientProvision.Apply();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;5． 运行该控制台程序。&lt;/p&gt;&lt;p&gt;6． 在SQL Server Management Studio中，依次展开 SQL Server Compact [My Computer\...\SyncCompactDB] 节点和&amp;ldquo;表&amp;rdquo;，此时您应会看到设置过程创建的以下附加表：Products_Tracking、schema_info、scope_config 和 scope_info。还有设置过程创建的其他对象，例如触发器和存储过程。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;执行同步&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在前面的步骤中，您准备了服务器数据库 SyncDB 和Compact数据库 SyncCompactDB 以便进行同步。现在我们将创建一个控制台应用程序，该控制台应用程序将真正开始这两个数据库之间的同步过程。&lt;/p&gt;&lt;p&gt;1．&amp;nbsp; 为SyncSQLServerAndSQLCompact解决方案添加一个新的控制台应用程序，项目名称为ExecuteCompactSync。&lt;/p&gt;&lt;p&gt;2．&amp;nbsp; 添加对Microsoft.Synchronization、Microsoft.Synchornization.Data、Microsoft.Synchronization.Data.SqlServer、Microsoft.Synchronization.Data.SqlServerCe程序集的引用。&lt;/p&gt;&lt;p&gt;3．&amp;nbsp; 添加对 System.Data.SqlServerCe 程序集的引用。&lt;/p&gt;&lt;p&gt;4．&amp;nbsp; 按下面的代码完成该控制台应用程序：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Data;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Data.SqlClient;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Data.SqlServerCe;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data.SqlServer;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Data.SqlServerCe;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt; ExecuteCompactSync&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建到SyncCompactDB database的连接&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlCeConnection clientConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeConnection(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source='D:\Sync Framework\CompactDB\SyncCompactDB.sdf'&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建到SyncDB服务器数据库的连接&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SqlConnection serverConn = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlConnection(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Data Source=localhost; Initial Catalog=SyncDB; Integrated Security=True&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;创建同步代理（sync orhcestrator）&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SyncOrchestrator syncOrchestrator = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SyncOrchestrator();&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;设置同步代理的本地同步提供程序为SyncCompactDB compact database的ProductsScope&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            syncOrchestrator.LocalProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlCeSyncProvider(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductsScope&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, clientConn);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;设置同步代理的远程同步提供程序为SyncDB server database的ProductsScope&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            syncOrchestrator.RemoteProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SqlSyncProvider(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductsScope&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, serverConn);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;设置同步会话的同步方向为Upload和Download&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            syncOrchestrator.Direction = SyncDirectionOrder.UploadAndDownload;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;侦听本地同步提供程序的ApplyChangeFailed事件&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            ((SqlCeSyncProvider)syncOrchestrator.LocalProvider).ApplyChangeFailed += &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; EventHandler&amp;lt;DbApplyChangeFailedEventArgs&amp;gt;(Program_ApplyChangeFailed);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;执行同步过程&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SyncOperationStatistics syncStats = syncOrchestrator.Synchronize();&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;输出统计数据&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Start Time: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.SyncStartTime);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Total Changes Uploaded: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.UploadChangesTotal);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Total Changes Downloaded: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.DownloadChangesTotal);&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Complete Time: &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt; + syncStats.SyncEndTime);&lt;br /&gt;            Console.WriteLine(String.Empty);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Program_ApplyChangeFailed(&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; sender, DbApplyChangeFailedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;显示冲突类型&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            Console.WriteLine(e.Conflict.Type);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;显示错误信息&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            Console.WriteLine(e.Error);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;5．&amp;nbsp; 在&amp;ldquo;解决方案资源管理器&amp;rdquo;中，将ExecuteCompactSync项目设置为启动项目。&lt;/p&gt;&lt;p&gt;6．&amp;nbsp; 执行该控制台应用程序，你应该能看到如下输出。可以看到，位于 SyncDB 服务器数据库的 Products 表中的三条记录已经下载到Compact客户端数据库中了，我们可以在SSMS中进行确认。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030913383142.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;7．&amp;nbsp; 在 SQL Server Management Studio 中，为SyncDB服务器数据库的Products表添加一条记录：（ID=4，Name=&amp;rdquo; Wireless Mouse&amp;rdquo;，ListPrice=45）。&lt;/p&gt;&lt;p&gt;8．&amp;nbsp; 在 Visual Studio 中，再次执行同步客户端程序。您应该看到如下输出。我们可以在SSMS中确认该条新记录是否已经同步至Compact客户端数据库了。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030913390638.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;我们可以通过在服务器/客户端添加/更新/删除记录，反复试验以便熟悉Sync Framework技术。例如，如果您从服务器删除一条记录，则在您下次将客户端与服务器同步时，应该删除客户端数据库中相应的记录。如果在客户端添加记录，同步时也会上传到服务器数据库。&lt;/p&gt;&lt;p&gt;应园友的要求，本解决方案的源代码已经上传，需要的朋友请&lt;a href="http://files.cnblogs.com/lifepoem/SyncSQLServerAndSQLCompact.zip"&gt;点此下载&lt;/a&gt;。运行时请参照文中的具体步骤与前提条件，比如数据库的创建等。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2387497.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387497.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387151.html</id><title type="text">Microsoft Sync Framework同步数据库 1：同步数据库简介</title><summary type="text">Sync Framework 支持在数据库之间进行同步。它提供了一个直观且灵活的 API，使您可以生成面向脱机和协作方案的应用程序。通过该 API，您可以根据应用程序的体系结构和要求，使用所提供的所有或部分组件来完成同步工作。Sync Framework 支持客户端-服务器、客户端到客户端和混合拓扑。在客户端-服务器拓扑中，所有客户端都与某一中央服务器同步。在客户端到客户端拓扑中，每个客户端都可以与其他客户端同步，而变更不必通过中央服务器来传递。混合拓扑由客户端到客户端拓扑和客户端-服务器拓扑组合而成。</summary><published>2012-03-09T02:33:00Z</published><updated>2012-03-09T02:33:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387151.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387151.html"/><content type="html">&lt;p&gt;&lt;strong&gt;同步数据库简介&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;概述&lt;/p&gt;&lt;p&gt;Sync Framework 支持在数据库之间进行同步。它提供了一个直观且灵活的 API，使您可以生成面向脱机和协作方案的应用程序。通过该 API，您可以根据应用程序的体系结构和要求，使用所提供的所有或部分组件来完成同步工作。&lt;span style="text-decoration: underline;"&gt;Sync Framework 支持客户端-服务器、客户端到客户端和混合拓扑。&lt;/span&gt;在客户端-服务器拓扑中，所有客户端都与某一中央服务器同步。在客户端到客户端拓扑中，每个客户端都可以与其他客户端同步，而变更不必通过中央服务器来传递。混合拓扑由客户端到客户端拓扑和客户端-服务器拓扑组合而成。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;传统的分布式系统&lt;/span&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;随着计算机网路技术的飞速发展，特别是因特网计术的应用与普及，分布式计算机软件已经越来越重要了。毕竟，分布式技术为我们带来了数据共享，使得交互与协作成为可能。对于一家企业来说，能够支持移动和远程工作人员正在变得越来越重要。组织机构应确保这些工作人员能够像在办公室时一样访问到相同的信息，这一点非常重要。在大多数情况下，这些用户将使用便携式计算机、办公台式机、smartphone 或 PDA，远程用户使用这些设备通过网络访问数据仓库。但是这种传统的分布式解决方案存在着如下这些严重缺陷而无法获得满意的效果：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;网络要求&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;若要使用户能够访问信息，远程设备在访问数据时必须能够不间断地连接到公司网络。对于某些工作人员（如在家办公的人员），这可能并不是什么问题。但对于其他用户（如经常出差的销售人员），就可能会比较困难。例如，如果某一销售人员正在拜访客户，并且由于没有网络连接而无法访问库存数据，该销售人员将无法有效地完成工作。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;数据访问速度&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在典型的客户端-服务器公司环境中，用户拥有可快速访问信息的高速网络。但是，远程工作人员常常通过不太可靠的慢速网络进行连接。在使用典型的解决方案时，每次当用户需要一份数据时，都必须进行下载，因为无法将数据长久地保存到设备上。例如，销售人员每次打开应用程序时，都必须下载其产品列表，而使用信息填充应用程序所需的时间可能非常长，这让用户非常苦恼。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;单个故障点&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;使用这种解决方案时，用户常常依赖于单个服务器数据库。如果数据库由于计划的服务器停机或意外的服务器故障而无法使用，所有远程工作人员与其数据的连接将会中断。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;服务器可伸缩性&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;随着远程工作人员的数量不断增加，公司服务器的性能将会受到影响，并且可能需要添加更多的硬件。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;偶尔连接的应用程序&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在对于传统分布式系统解决方案的一种替代方案是实现偶尔连接的应用程序。偶尔连接的应用程序仍使得远程工作人员能够访问数据，但其所需的信息在本地存储。&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;偶尔连接的应用程序通常使用数据同步来填充本地数据库。&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;数据同步包括以下功能：定期获取存储在一个数据库（如客户端数据库）中的信息并与其他数据库（如服务器数据库）同步变更。基于同步的解决方案的优点在于：用户不再必须使用不间断的网络连接来访问信息。由于将数据存储在本地，用户可以随时访问数据，同时还减轻了中心数据库的处理负载。此外，由于网络速度不再是限制因素，用户现在能够以本地计算机的速度来访问数据。&lt;/p&gt;&lt;p&gt;客户端到客户端同步可避免发生单点故障，因为它使同步不依赖于所有变更均需通过服务器。这种将大量应用程序处理推向每个客户端的功能还有助于解决服务器可伸缩性问题。&lt;/p&gt;&lt;p&gt;是的，正如我们看到的，偶尔连接的应用程序非常适合解决因网络问题不能一直保持连接的程序，并且能改善系统性能，增强可靠性。而我们需要做的就是，需要在本地数据库和远程数据库中进行数据同步。Sync Framework就对数据库同步这种场景提供了优秀和完整的支持，使我们免于自己为每个系统去实现复杂的同步逻辑和异常处理。&lt;/p&gt;&lt;p&gt;Sync Framework 支持在数据库之间进行同步。它提供了一个直观且灵活的 API，使您可以生成面向脱机和协作方案的应用程序。通过该 API，您可以根据应用程序的体系结构和要求，使用所提供的所有或部分组件。Sync Framework 支持客户端-服务器、客户端到客户端和混合拓扑。&lt;/p&gt;&lt;p&gt;Sync Framework 使用&amp;ldquo;同步提供程序(Synchronization Providers)&amp;rdquo;与同步的每个数据库进行通信。Sync Framework 数据库提供程序（与 ADO.NET 数据提供程序类似）保护其他 Sync Framework 组件不受各数据库的特定实现方式的影响。Sync Framework 包括五个数据库提供程序，这些提供程序支持两种方案：脱机和协作方案。下图显示一个&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;脱机方案：在客户端&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;-&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;服务器拓扑中，多个客户端连接到一个中央服务器，以便在连接可用时同步数据。&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030910200310.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;这种偶尔连接的应用程序的一个常见扩展是支持协作应用方案的能力。&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;在协作方案中，两个数据库可以通过对等方式进行同步，而无需通过中央集线器。&lt;/span&gt;&lt;/strong&gt;下图显示一个混合拓扑，其中，一个中央服务器与多个客户端同步，并且这些客户端能够彼此同步。此类拓扑可以支持允许用户共享项目备注的应用程序。项目团队成员常常要求他们可处理的数据的本地副本。当他们进行变更时，他们可以与服务器同步以上载变更，或与其他团队成员同步以交换变更。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030910201998.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;数据库同步提供程序&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Sync Framework包含的3个主要的数据库同步提供程序同时适用于脱机方案和协作方案，支持客户端-服务器，客户端-客户端和混合拓扑。我们可以各种方式组合使用这些提供程序来对我们选择的拓扑方案进行同步。因为Sync Framework元数据的使用，他们甚至可以和其他的Sync Framework提供程序进行同步。这3个同步提供程序如下：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;SqlSyncProvider&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;对SQL Server、SQL Server Express、和SQL Azure databases进行同步。&lt;/li&gt;&lt;li&gt;提供丰富和可配置的准备工具来为数据库建立必要的同步结构，比如元数据表和存储过程。&lt;/li&gt;&lt;li&gt;包含了灵活的过滤选项用以对需要同步的表按行或列进行过滤，基于参数的过滤机制支持最大限度的重用数据库元素。&lt;/li&gt;&lt;li&gt;提供了相应组件来帮助我们管理同步元数据，包括清除元数据和恢复元素据（当我们从一个备份中恢复数据库时）。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;SqlCeSyncProvider&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;对SQL Server Compact databases进行同步&lt;/li&gt;&lt;li&gt;提供简化的准备工具来为数据库建立必要的同步结构，比如元数据表和存储过程。&lt;/li&gt;&lt;li&gt;可以基于之前准备的SQL Server Compact database 快照高效的创建新的SQL Server Compact databases。&lt;/li&gt;&lt;li&gt;提供了相应组件来帮助我们管理同步元数据。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;DbSyncProvider&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;通常用于同步ADO.NET兼容的非 SQL Server 数据库。&lt;/li&gt;&lt;li&gt;提供了功能完备的API以允许任何ADO.NET兼容的数据库来进行同步工作。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Offline-Only Providers&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;另外两个数据库同步提供程序只支持脱机方案。这些提供程序已经被上述同时支持脱机方案和协作方案的提供程序取代。所以对于新开发的应用程序，请使用上面介绍的提供程序。脱机方案提供程序包括：&lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.synchronization.data.server.dbserversyncprovider(v=sql.110).aspx"&gt;DbServerSyncProvider&lt;/a&gt;、&lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.synchronization.data.sqlserverce.sqlceclientsyncprovider(v=sql.110).aspx"&gt;SqlCeClientSyncProvider&lt;/a&gt; 。&lt;/p&gt;&lt;p&gt;这两个提供程序具备如下特征：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;适合于客户端-服务器拓扑。&lt;/li&gt;&lt;li&gt;总是成对使用。例如，您不能通过使用 ServerSyncProvider 的两个实例同步两个服务器数据库（改为使用 SqlSyncProvider 或 DbSyncProvider）。&lt;/li&gt;&lt;li&gt;可能没有协作提供程序复杂，但无法与其他 Sync Framework 提供程序一起参与拓扑。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;数据库同步的体系结构和类&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;数据库同步体系结构&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在脱机和协作方案中，Sync Framework可以用在两层和N层架构中。在任何一种架构中，下面的活动发生在一个同步会话中：一个synchronization orchestrator与两个同步提供程序进行通讯来对数据库进行获取和应用变更。同步提供程序使用包含了相关SQL Commands的同步适配器(synchronization adapter)来为每个表进行同步。一些提供程序公开这些适配器以允许我们对这些SQL命令进行定制，另外一些提供程序则自动生成适配器来降低同步工作的复杂度。&lt;/p&gt;&lt;p&gt;下图显示了一个两层架构：一个同步会话中的所有组件都位于本地计算机，包含一个直接连接远程数据库的连接。在同步会话中，本地计算机是指发起同步的计算机。如果我们希望对多个计算机进行同步，每个计算机都必须包含图中所示的所有组件。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030910243663.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;下图显示了一个N层架构：这种架构需要额外的组件，包括远程计算机中的组件和service，本地计算机上的proxy(代理)将会处理到远程数据库的连接。开发人员必须自己实现proxy和service。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030910245965.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;参与同步的数据库可以是SQL Server 2005 SP2或之后的任意版本，包括SQL Server Compact 3.5 SP2及以后版本、SQL Azure、或提供了ADO.NET提供程序的其他数据库。Sync Framework为SQL Server和SQL Server Compact databases自动配置了变更跟踪和元数据存储。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Sync Framework类&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a title="Collapse" href="javascript:void(0)"&gt; SyncOrchestrator&lt;/a&gt;（同步代理）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步代理通过以下方式驱动同步过程：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;基于Direction属性来决定应用改变的顺序和方向。&lt;/li&gt;&lt;li&gt;调用服务器同步提供程序以对服务器数据库进行检索和应用变更。&lt;/li&gt;&lt;li&gt;调用客户端同步提供程序以对客户端数据库进行检索和应用变更。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;此外，同步代理还维护同步操作的会话级别信息，并向客户端上的应用程序提供成功消息、错误和统计信息。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;SyncProvider (SqlSyncProvider, SqlCeSyncProvider, 和DbSyncProvider)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步提供程序与相应的数据库进行通信，并将同步代理和数据库的特定实现屏蔽开来。对于SQL Server Compact databases ，使用SqlCeSyncProvider；而对于其他版本的SQL Server，包括SQL Azure，使用SqlSyncProvider；对于非SQL数据库使用DbSyncProvider。这3种Providers都继承自RelationalSyncProvider。同步提供程序的主要活动如下所示：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;检索自上次同步以来在（本地）数据库中发生的变更。&lt;/li&gt;&lt;li&gt;对（远程）数据库应用增量变更。&lt;/li&gt;&lt;li&gt;检测发生冲突的变更。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;SyncAdapter (DbSyncAdapter和SqlCeSyncAdapter)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步适配器模仿 ADO.NET 中的数据适配器，并为进行同步的每个表定义同步适配器。同步适配器为同步提供程序提供了与数据库交互所需的特定SQL命令。&lt;/p&gt;&lt;p&gt;对于SqlSyncProvider和SqlCeSyncProvider使用的同步适配器，Sync Framework会自动生成相关SQL命令，这样可以降低同步的复杂度。对于DbSyncAdapter，我们需要自己来创建适配器和指定相关SQL命令，例如 InsertCommand，此命令可从客户端数据库向服务器数据库应用插入。由于同步适配器使用 ADO.NET DbCommand 对象，因此可以使用 ADO.NET 支持的任意命令结构。这包括内联 Transact-SQL、存储过程、视图、函数等。这些命令只需要定义了要传输和应用的结构和数据的单个结果。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;API中的其他类&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;上图展示了 API 中主要的类。但是，还有许多类没有在图中展示出来。若要获取有关所有可用类的信息，可以参见 Microsoft.Synchronization、Microsoft.Synchronization.Data、Microsoft.Synchronization.Data.SqlServerCe 和 Microsoft.Synchronization.Data.Server这是个dll中详细的API定义。以下部分介绍了您应该熟悉的其他重要的类。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;DbSyncScope&lt;/strong&gt;&lt;strong&gt;（同步作用域）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步作用域是对进行同步的对象的一种逻辑分组。对于数据库同步，一个同步组通常是一组数据表，并且数据表可以被过滤。同时一个数据表可以被包含在一个或多个同步组中。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Database Provisioning Objects&lt;/strong&gt;&lt;strong&gt;（数据库准备对象）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于SQL Server和SQL Server Compact databases，Sync Framework提供了一组类用来描述同步组和每个同步组中包含哪些数据表。在这些表和同步组被定义后，我们就可以使用Sync Framework对象来对每个节点应用准备脚本（provisioning scripts）。这些脚本创建了一个变更跟踪和变更应用的基础架构，包含了metadata tables, triggers, 和stored procedures。下表列出了用来准备数据库和提供程序的相关类：&lt;/p&gt;&lt;table border="1" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;&lt;tr bgcolor="#cccccc"&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;&lt;strong&gt;SQL Server、SQL Azure&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;&lt;strong&gt;SQL Server Compact&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;DbSyncScopeDescription&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;DbSyncScopeDescription&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示同步作用域，同步作用域是作为一个单元同步的表（可筛选）的逻辑分组。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;SqlSyncScopeProvisioning&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;SqlCeSyncScopeProvisioning&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示用于特定作用域的 SQL Server、SQL &amp;nbsp; Azure 或 &amp;nbsp; SQL Server Compact 数据库的设置&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;SqlSyncProviderScopeConfiguration&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;SqlCeSyncProviderScopeConfiguration&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示针对特定作用域的 SqlSyncProvider 或 &amp;nbsp; SqlCeSyncProvider 使用的配置信息。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;DbSyncTableDescription&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;DbSyncTableDescription&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示在同步作用域中包括的表的架构。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;DbSyncColumnDescription&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;DbSyncColumnDescription&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示属于在同步作用域中包括的表的列的架构。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;SqlSyncDescriptionBuilder&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;SqlCeSyncDescriptionBuilder&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示同步中涉及的 SQL Server、SQL &amp;nbsp; Azure 或 &amp;nbsp; SQL Server Compact 数据库的作用域和表信息。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;SqlSyncTableProvisioning&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;SqlSyncTableProvisioning&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示由DbSyncTableDescription 对象表示的SQL &amp;nbsp; Server, SQL Azure, 或SQL Server Compact database设置。&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign="top" width="26%"&gt;&lt;p&gt;SqlSyncProviderAdapterConfiguration&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="28%"&gt;&lt;p&gt;SqlSyncProviderAdapterConfiguration&lt;/p&gt;&lt;/td&gt;&lt;td valign="top" width="45%"&gt;&lt;p&gt;表示某个数据库表的同步适配器配置信息&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;SyncOperationStatistics&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;会话统计信息是同步代理为每个同步会话提供的一组统计信息。统计信息包括与同步时间、所处理的变更数量以及所发生的任何冲突或异常有关的信息。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;DbSyncSession&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;DbSyncSession对象提供了对同步会话变量的访问。会话变量是一些为开发人员提供的变量，用作在服务器上执行的选择、插入、更新和删除命令的参数。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Sync Framework DLLs&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Sync Framework中的数据库同步类包含在如下这些DLLs中：&lt;/p&gt;&lt;p&gt;Microsoft.Synchronization.dll，包含了SyncOrchestrator。&lt;/p&gt;&lt;p&gt;Microsoft.Synchronization.SqlServer.dll，包含了SqlSyncProvider。&lt;/p&gt;&lt;p&gt;Microsoft.Synchronization.SqlServerCe.dll，包含了SqlCeSyncProvider。&lt;/p&gt;&lt;p&gt;Microsoft.Synchronization.Data.dll，包含了RelationalSyncProvider, DbSyncProvider 和DbSyncAdapter。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;本篇讲述了数据库同步的背景和优势以及具体的数据库同步提供程序，也讲述了其体系结构和重要的同步类，下一篇我们将通过一个完整的实例来展示如何使用这些提供程序和相关类来完成我们的同步任务。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2387151.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387151.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2012/03/08/2385290.html</id><title type="text">Microsoft Sync Framework基础篇 3：Microsoft Sync Framework元数据和同步流程</title><summary type="text">在本篇博客中，我们将详细的了解和学习通用的元数据模型以及它的组件，当然，我们也会讨论Sync Framework如何使用元数据来同步不同的数据存储和副本。并以一个文件同步实例来讲述了Microsoft Sync Framework的同步流程。</summary><published>2012-03-08T07:00:00Z</published><updated>2012-03-08T07:00:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2385290.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2385290.html"/><content type="html">&lt;p&gt;&lt;strong&gt;Microsoft Sync Framework元数据和同步流程&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;元数据(Metadata)&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Microsoft Sync Framework为脱机和协作的应用程序、数据存储和设备提供了一个完整的同步平台，而不用考虑如下限制：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;同步的数据类型&lt;/li&gt;&lt;li&gt;数据存储的类型&lt;/li&gt;&lt;li&gt;传输协议&lt;/li&gt;&lt;li&gt;网络拓扑比如点对点或客户端-服务器拓扑&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;相反，Sync Framework通过一个通用的元数据模型来允许Sync Framework完成下面的工作：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;实现同步过程的互操作性&lt;/li&gt;&lt;li&gt;减少在两个参与同步的data stores之间的数据传输量&lt;/li&gt;&lt;li&gt;使同步独立于任何网络拓扑、数据类型、数据存储和传输协议&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在本篇博客中，我们将详细的了解和学习通用的元数据模型以及它的组件，当然，我们也会讨论Sync Framework如何使用元数据来同步不同的数据存储和副本。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;什么是元数据&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;从字面意义上看，元数据是&amp;ldquo;关于数据的数据&amp;rdquo;。而Microsoft Sync Framework中使用的元数据包含两种类型：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;副本元数据（Replica metadata）&lt;/li&gt;&lt;li&gt;项目元数据（Item metadata）&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在Sync Framework中，副本通常是指真正的数据存储。比如，如果我们在同步两个数据库，那么每个数据库都是一个副本，副本可以包含项目。比如，对于数据库，一个项目可以是表中的一条记录。&lt;/p&gt;&lt;p&gt;要同步两个副本， Sync Framework要求同步提供程序使用通用的元数据模型，这也是Sync Framework的核心所在。Sync Framework提供程序使用元数据来检测副本的更新，但是提供程序本身并不要求理解同步元数据（这是Sync Framework运行时的职责所在，它会帮助提供程序来解析同步元数据）。&lt;/p&gt;&lt;p&gt;同步提供程序通过运行时来查询元数据，以发现某个副本自上一次同步以来所作的数据更新。同步元数据还帮助完成对冲突的检测和处理。冲突是指在同步过程中，同一项目在两个副本中被同时修改。同步提供程序使用元数据来判断一个项目是否处于冲突状态并使用元数据来解决冲突。同步元数据还会被Sync Framework运行时使用，以解决通常的同步问题比如网络失败、冲突数据和应用程序错误。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;元数据存储（Metadata Store）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;你可能会对元数据存放在何处感到好奇，实际上，元数据可以存放在任何地方：一个文件、一个单独的数据库或参与同步的副本上。我们唯一需要保证的就是该元数据存储是可以通过编程来进行访问的。Sync Framework通过调用同步提供程序的不同方法来获取和更新元数据。在实现自己的元数据存储时，我们需要在相应方法被执行时返回和修改我们的元数据。&lt;/p&gt;&lt;p&gt;但多数情况下，我们会把对元数据进行操作的任务托管给Sync Framework运行时，这是因为Microsoft Sync Framework 提供一个以 SQL Server Compact Edition 为基础的完整元数据存储实现，如下图所示。该存储并非必要，但使用它意味着您不必担心如何存储同步元数据。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814485266.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;使用内置的元数据存储还是自定义的元数据存储，取决于创建同步程序的开发人员。但使用内置的元数据存储意味着您不必担心如何存储同步元数据。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步元数据组件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;用于数据存储的元数据可以分为三个主要组件：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;版本（Version）&lt;/li&gt;&lt;li&gt;知识（Knowledge）&lt;/li&gt;&lt;li&gt;Tombstones&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;版本（Version）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步版本和副本中的项目相关联：该信息记录了项目在何时何处被创建和发生的变化，以及与该项目关联的项目ID。比如在数据库同步中，同步的数据库可以成为副本A和副本B。一个项目可能是数据库中的一个表，或表中的以条记录，甚至是表中某行的一列。&lt;/p&gt;&lt;p&gt;当项目发生更改时，存储的有关该更改的信息将包括&lt;strong&gt;创建版本&lt;/strong&gt;和&lt;strong&gt;更新版本&lt;/strong&gt;。这些版本包含两个组件：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;滴答计数 ：它是一个在整个源副本范围内使用以唯一标识一个更改的逻辑时钟&lt;/li&gt;&lt;li&gt;副本ID：它用于唯一标识发生更改的数据存储。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;当首次创建项目时，创建版本与更新版本相同。对该项目的后续更新修改的只是更新版本。&lt;/p&gt;&lt;p&gt;举个例子，假如参与同步的副本A中Customer表的数据如下：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814491323.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;假设我们使用表中ID字段作为项目ID，那么表中记录的版本信息可以用下表来表示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814492972.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;记录项目版本的过程也叫更改跟踪（change tracking）。要实现更改跟踪，同步提供程序需要为副本中任何时候的修改项目更新其同步版本。更改跟踪（版本）的实现主要有两种方式：&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;内联跟踪：&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在这种方法中，版本的修改在副本中的项目被修改时发生。这种方法通常用在我们可以将修改版本信息的方法嵌入到副本本身时，以数据库为例，我们可以使用触发器在更新行之后立即更新更改跟踪表。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;异步跟踪：&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在这种方法中，将运行外部进程来扫描更改。发现的任何更新将添加到版本信息当中。该进程可能是定期执行进程的一部分，或者它可能在同步之前执行。该进程通常用于当没有内部机制能够在项目更新时自动更新版本信息的情况中（例如，无法在更新流程中增加版本更新逻辑）。检查更改的常用方式是存储项目的状态，并将存储的状态与项目当前状态进行比较。例如，可检查从上次同步起，最后写入时间或文件大小是否发生变化。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;知识（Knowledge）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;知识是副本能够感知的数据更改的精简表示。版本和项目相关联，而知识则是和sync scope（同步作用域）相关联。知识包含了在一个副本上直接或间接所作修改的信息。同步提供程序通常不会直接使用知识，取而代之的是，Sync Framework运行时会调用提供者的方法来操作副本的知识。知识的目的在于使同步更加有效，因为它有助于限制在副本之间发送的信息量。当版本信息更新时，用于数据存储的知识也随之更新。&lt;/p&gt;&lt;p&gt;提供程序使用副本知识的目的有：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;枚举更改：确定另一个副本没有感知的更改。&lt;/li&gt;&lt;li&gt;检测冲突：确定哪项操作是在不了解彼此知识的情况下做出的。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;一个副本的知识由副本ID和副本中最大的滴答计数组合而成，以上面的数据库同步为例，包含Customer表的副本A的知识为A2。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tombstones&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;每个副本还必须为每个删除的项目维护tombstone 信息。如果不跟踪删除信息，提供程序将无法告知某个项目（如文件）已被删除。在这种情况下，提供程序无法将更改版本信息发送至其他提供程序。Tombstone 必须包含以下信息：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;全局 ID： 用于在所有副本中唯一确定 tombstone 项目的副本 ID 和滴答计数。&lt;/li&gt;&lt;li&gt;删除版本： 与 tombstone 项目关联的更新版本&lt;/li&gt;&lt;li&gt;创建版本： 最初创建项目时关联的副本 ID 和滴答计数&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;因为 tombstone 日志中的信息将随时间增加，所以有必要创建一个进程定期清理该存储。清理 tombstone 数据能够节省空间并且有助于改善同步性能。Microsoft Sync Framework 支持对tombstone 信息的管理。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;同步流程&lt;/span&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;了解了同步元数据，我们就可以来学习同步流程了。发起同步的副本称为源 而源所连接的副本称为目标。本文接下来的部分将介绍下图所示的同步流程。对于双向同步，将执行此进程两次，第二次迭代时会交换源和目标。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814503322.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;1. 发起同步会话&lt;/p&gt;&lt;p&gt;在这一阶段将建立同步会话，从而创建了从源到提供程序的链接。&lt;/p&gt;&lt;p&gt;2. 目标准备并发送知识&lt;/p&gt;&lt;p&gt;如前所述，每个副本都会存储其自身的知识。存储在目标端的知识将传递到源。&lt;/p&gt;&lt;p&gt;3. 目标知识用于确定要发送的更改&lt;/p&gt;&lt;p&gt;在源端，会将刚刚收到的知识与本地项目版本进行比较，以确定目标端尚不了解的项目。值得注意的是，发送的版本并不是实际的项目，而是每个项目上次发生更改的位置摘要。&lt;/p&gt;&lt;p&gt;4. 更改版本和源知识发往目标端&lt;/p&gt;&lt;p&gt;当源准备好所需的更改版本列表之后，这些版本将传输到目标端&lt;/p&gt;&lt;p&gt;5. 检索更改项目的本地版本并与源版本和知识进行比较&lt;/p&gt;&lt;p&gt;目标端使用这些版本准备源需要发送的项目列表。目标还使用该信息检测是否存在限制冲突。限制冲突是指违反了项目限制，如文件夹关系或文件系统中同名数据的位置。&lt;/p&gt;&lt;p&gt;6. 检测并解决或推迟冲突&lt;/p&gt;&lt;p&gt;基本上，如果在两次同步期间对两个副本上的相同项目进行更改就会发生冲突。在 Microsoft Sync Framework 运行时中，当其中一个副本的更改版本不包含另一个副本更改的知识时便会检测到冲突。&amp;nbsp;&amp;nbsp; 将在下面的&amp;ldquo;冲突示例&amp;rdquo;部分中介绍了说明该检测过程如何工作的更加详细的示例。&lt;/p&gt;&lt;p&gt;副本可以自由实施各种策略，解决同步拓扑间发生冲突的项目。下面列举了一些常用的冲突解决策略：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;源获胜： 当检测到冲突时，总是采用源副本所做的更改。&lt;/li&gt;&lt;li&gt;目标获胜： 总是采用目标副本所做的更改。&lt;/li&gt;&lt;li&gt;合并： 将源副本和目标副本所做的更改合并在一起。库存统计可能是一个您希望将两个副本的值合并（求和），而不是选取其中一个作为正确值的例子。&lt;/li&gt;&lt;li&gt;记录冲突： 记录或推迟冲突。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;7. 目标向源请求项目数据&lt;/p&gt;&lt;p&gt;在这一阶段，目标已经确定需要在源中检索的项目，并将请求发送到源。&lt;/p&gt;&lt;p&gt;8. 源准备并发送项目数据&lt;/p&gt;&lt;p&gt;源接收到项目数据请求，并准备要传输到目标的实际数据。如果要跟踪的项目是数据库中的一行，则将发送该行。如果项目是文件夹中的文件，则将传送该文件。&lt;/p&gt;&lt;p&gt;9. 项目应用到目标中&lt;/p&gt;&lt;p&gt;目标接收并应用项目。如果在此过程中出现任何错误（如网络断开），则该项目将被标记为异常，并在下次同步期间进行更正。从源接收的知识将添加到目标知识。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="background-color: #c0c0c0;"&gt;&lt;strong&gt;同步示例&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;通过使用前面介绍的同步流程，我们将实际操作一次文件同步示例，该示例将说明 Microsoft Sync Framework 如何通过元数据来枚举更改并最终应用项目数据。在本例中有两个副本：副本 A 和副本 B。副本 A 启动与副本 B 的同步（即副本 A 是源而副本 B 是目标）。假定我们希望同步两个副本间的文件。要跟踪的项目是文件夹中的一个文件，表示为 In （例如，I1, I2, I3&amp;hellip;）。创建新文件时 (I1) 与该文件相关联的元数据应更新如下：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814514528.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;如果文件再次更新，版本表应如下所示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814520657.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;在上述示例中，更新滴答计数设置为 5，这是由于用于滴答计数的逻辑时钟在整个源内发挥作用，即：滴答计数 2-4 已用于副本中其他项目的更改。&lt;/p&gt;&lt;p&gt;例如，在下面的图例中，跟踪的副本中有两个附加的项目 I2 和 I3 。您可以看到，随着创建更多的项目，版本信息将变得越来越多。Microsoft Sync Framework 不要求存储以前的更新版本。它只需要了解最新的更新版本。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814522875.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;如果采用该副本的当前项目状态，我们可以把副本 A 的知识表示为：&lt;/p&gt;&lt;p&gt;副本 A 知识 = A5&lt;/p&gt;&lt;p&gt;如前所述，知识是副本能够感知的数据更改的简约表述。在本例中，A 是分配给该副本的唯一 ID，而 5 是当前滴答计数，它使副本能够了解当前的最大变化个数。如果该副本已经与任意其他副本进行同步，则我们还将在该列表中看到这一知识。&lt;/p&gt;&lt;p&gt;在副本 B 上可能也有很多文件。该副本如下所示：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;副本 B&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814524523.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;副本 B 的当前知识为：&lt;/p&gt;&lt;p&gt;副本 B 知识 = B4&lt;/p&gt;&lt;p&gt;此时我们选择开始在两个副本之间进行同步。副本 A 将成为源（启动同步的副本），副本 B 将成为目标。&lt;/p&gt;&lt;p&gt;同步过程中，目标向源发送其知识。如前所述，两个副本的知识如下：&lt;/p&gt;&lt;p&gt;副本 A 知识 = A5&lt;/p&gt;&lt;p&gt;副本 B 知识 = B4&lt;/p&gt;&lt;p&gt;源（副本 A）收到该知识并使用它来确定将哪个版本发送到目标。由于副本 B 不了解在副本 A 中的任何项目，所以它将发送所有内容。在本例中，副本 A 将包含以下版本。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;副本 A &lt;/strong&gt;&lt;strong&gt;的更改批次&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814531072.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;目标接收这些版本并对其进行枚举以确定需要从源请求哪些项目。它还使用该信息确定是否存在任何冲突（例如，在两个副本上更新了相同的文件）。&lt;/p&gt;&lt;p&gt;完成后，目标请求源发送它没有感知的项目。在本例中，副本 A 将发送与 I1、 I2 和 I3。&lt;/p&gt;&lt;p&gt;目标收到这些文件并将其添加到自己的文件夹中。副本 B 的项目现在将包含从副本 A 接收到的项目。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;副本 B &amp;ndash; &lt;/strong&gt;&lt;strong&gt;已更新项目表&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814532616.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;本次同步结束后，该过程将再执行一遍，这次源将成为目标而目标成为源。这使得副本 A 能够接收到在副本 B 上创建或更改的任何文件（I104 和 I105）。&lt;/p&gt;&lt;p&gt;同步完成后，两个副本上都应包含以下更新知识。&lt;/p&gt;&lt;p&gt;副本 A 知识 = A5， B4&lt;/p&gt;&lt;p&gt;副本 B 知识 = A5， B4&lt;/p&gt;&lt;p&gt;&lt;strong&gt;冲突示例&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;继续前面的示例，两个副本现在已经&amp;ldquo;同步&amp;rdquo;，并且每个项目标版本如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814540230.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;类似地，两个副本的知识如下：&lt;/p&gt;&lt;p&gt;副本 A 知识 = A5， B4&lt;/p&gt;&lt;p&gt;副本 B 知识 = A5， B4&lt;/p&gt;&lt;p&gt;此时，两个副本都决定更新相同的文件（项目 I2）。&lt;/p&gt;&lt;p&gt;在副本 A 上，该项目标版本表更新为：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814543274.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;在副本 B 上，该项目标版本表更新为：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814544494.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;两个副本的知识也更新为：&lt;/p&gt;&lt;p&gt;副本 A 知识 = A6， B4&lt;/p&gt;&lt;p&gt;副本 B 知识 = A5， B5&lt;/p&gt;&lt;p&gt;此时，副本 A 启动与副本 B 的同步。跳过源向目标发送项目版本和知识这一步，为项目 I2 执行下列步骤。&lt;/p&gt;&lt;p&gt;1. 副本 B 看到项目 I2 新更改，其为：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814550121.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;2. 副本 B 查看从副本 A 收到的知识（A6、B4）并确定副本 A 不了解由副本 B 对相同项目所做的更改：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030814553272.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;3. 将检测到冲突并传给应用程序或提供程序进行处理。&lt;/p&gt;&lt;p&gt;如前所述，应用程序能够选择如何处理冲突或延后处理。如果冲突延后处理，则在其解决之前它将在每次同步时重复出现。一旦冲突得到解决，则下一次同步时，原始副本将接收更新后的值。&lt;/p&gt;&lt;p&gt;在系列博客的第一部分基础篇中，通过3篇文章我们了解了同步的背景知识、同步的优点以及Microsoft Sync Framework对同步的实现；讲述了Sync Framework的核心组件和系统架构、各种同步参与方类型；详细的讨论了Sync Framework元数据的作用、同步流程，并实例展示了运行时是如何使用元数据来完成同步的。至此，我们对于Sync Framework的理论基础应该有了一个比较好的理解和掌握，接下去，我们将会详细的讨论使用具体的同步提供程序(Synchronization Providers)来同步各种数据，如数据库、文件、Web Feeds...&lt;/p&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2385290.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2385290.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2012/03/08/2384758.html</id><title type="text">Microsoft Sync Framework基础篇 2：Microsoft Sync Framework架构与运行时</title><summary type="text">本篇会先为大家介绍同步的各种参与方，参与方的类型决定了我们是否能够存储元数据，以及是否能够直接启动同步过程。然后会和大家详细讨论Microsoft Sync Framework的核心组件和系统架构，以让大家对Sync Framework有一个全局性的认识和了解。</summary><published>2012-03-08T01:59:00Z</published><updated>2012-03-08T01:59:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2384758.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2384758.html"/><content type="html">&lt;p&gt;&lt;strong&gt;Microsoft Sync Framework架构与运行时&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本篇会先为大家介绍同步的各种参与方，参与方的类型决定了我们是否能够存储元数据，以及是否能够直接启动同步过程。然后会和大家详细讨论Microsoft Sync Framework的核心组件和系统架构，以让大家对Sync Framework有一个全局性的认识和了解。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Sync Framework参与方（Participants）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在讨论Sync Framework核心组件之前，我们需要首先了解Sync Framework 支持的不同类型的同步参加方。参与方是提供程序及其关联副本的组合，代表了同步的一端。要同步的副本（即信息仓库）可以是取自 Web 服务、笔记本电脑、乃至 U 盘中的任何对象。&lt;/p&gt;&lt;p&gt;Microsoft Sync Framework 支持三种类型的参与方：完整、部分和简单。参与方的类型由其存储和处理同步元数据的能力决定。至少，我们可以假定如有请求，副本具备通过程序返回信息的能力。最后需要确定的是副本是否能够：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;在现有设备上或当前数据存储中存储和操作信息，并&lt;/li&gt;&lt;li&gt;允许应用程序（我们称之为同步提供程序）直接在设备上执行&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;区分参与方的类型对于同步生态系统来说十分重要，因为它使我们了解到该参与方是否能够存储提供程序所需的状态信息，以及我们是否能够直接在设备上运行提供程序。最终，参与方模型将成为通用模型。因此，可以将完整参与方配置为部分或简单参与方。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;完整参与方&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;完整参与方是指允许开发人员直接在设备上创建应用程序和新数据存储的设备。笔记本电脑和智能电话就属于完整参与方，因为可以直接从此类设备执行新的应用程序，并且如有必要，您还可以创建新的数据存储以保存信息。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030809485318.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;部分参与方&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;部分参与方是指能够在设备上存储数据的设备。但无法直接从这些设备上启动可执行程序。部分参与方的重要特性在于它能够存储同步所需的元数据，并因此得以与任何完整参与方进行同步。部分参与方的一个例子是 U 盘。这些设备类似于硬盘，能够创建、更新或删除信息。但通常它们不提供使应用程序能够直接在设备上运行的接口。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030809491457.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;简单参与方&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;简单参与方是指仅具备当接到请求时提供信息这一种能力的设备。此类设备不能存储或操作新数据，而且不支持创建新的应用程序。简单参与方依靠完整参与方存储其元数据（因此只能与特定的完整参与方进行同步）。&lt;/p&gt;&lt;p&gt;由外部组织（如 Amazon 或 EBay）提供的 RSS 源和 Web 服务都属于简单参与方。这些组织可能会赋予您执行 Web 服务并取回结果的能力，但不会赋予您在其 Web 服务器上创建您自己的数据存储或执行您自己应用程序的能力。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030809493337.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;组合同步参与方&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Microsoft Sync Framework 的最终目标是，无论数据源采用哪种参与类型，都允许对它们进行集成。因此，简单和部分参与方可以与完整参与方同步信息。但至少需要一个能够存储信息和启动同步过程的完整参与方。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Sync Framework核心组件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Sync Framework 包括一个运行时、用于特定数据存储区的一组&amp;ldquo;同步提供程序（synchronization providers）&amp;rdquo;以及用于编写提供程序的一个 API。提供程序是在数据源和同步系统中的其他组件之间进行通信的软件组件。如果Sync Framework已经为我们要同步的数据存储区提供了提供程序，强烈建议您使用该提供程序。提供程序具有可扩展性，以便您定制它们来适合您的应用程序。如果您要同步我们未提供提供程序的数据存储区或您需要其他实现，则请使用自定义提供程序。&lt;/p&gt;&lt;p&gt;下图显示了 Sync Framework 中所有组件之间的关系。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030809500373.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;该图中的组件如下所示：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;数据库同步提供程序（在以前的版本中称为 Sync Services for ADO.NET）。这些提供程序包含在 Microsoft.Synchronization.dll、Microsoft.Synchronization.Data.dll、Microsoft.Synchronization.Data.Server.dll、Microsoft.Synchronization.Data.SqlServer.dll 和 Microsoft.Synchronization.Data.SqlServerCe.dll 中。它们可用于在以下类型的方案中同步数据库：&lt;ul&gt;&lt;li&gt;协作方案。例如，在一个允许用户共享项目备注的应用程序中，项目团队成员通常需要一份可以处理的数据的本地副本。当他们进行变更时，可以与其他团队成员同步以交换变更，还可以与中央服务器同步变更。&lt;/li&gt;&lt;li&gt;脱机方案。例如，一个销售人员需要在客户的办公室访问产品数据，还必须能上载订单。该销售人员可以在每天早上与中央服务器同步以确保具有最新的产品和价格信息，然后在晚上执行同步以上载当天的订单。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;文件同步提供程序（在以前的版本中称为 Sync Services for File Systems）。此提供程序包含在 FileSyncProvider21.dll 和 Microsoft.Synchronization.Files.dll 中。它可用于同步 NTFS、FAT 或 SMB 文件系统中的文件和文件夹。要同步的目录可为本地或远程目录，且不必同属一个文件系统。应用程序可以使用静态筛选器通过显式列出文件或使用通配符（如 *.txt）来排除或包括这些文件；或者应用程序可以设置筛选器来排除整个子文件夹。应用程序还可以注册以接收文件同步进度的通知。&lt;/li&gt;&lt;li&gt;Web Feed同步组件（在以前的版本中称为 Sync Services for FeedSync）。这些组件包含在 FeedSync21.dll 和 Microsoft.Synchronization.dll 中。可以通过两种方式使用这些组件：&lt;ul&gt;&lt;li&gt;Web Feed同步提供程序服务可用于编写将 FeedSync XML 文件表示为其副本的提供程序。&lt;/li&gt;&lt;li&gt;Web Feed生成方和使用方组件可用于将其他类型的副本（如文件系统）的数据与 RSS 或 Atom Feeds同步。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;自定义提供程序。这些组件包含在 Synchronization21.dll 和 Microsoft.Synchronization.dll 以及 SimpleProviders21.dll 和 Microsoft.Synchronization.SimpleProviders.dll 中。它们可用于为任何类型的数据存储区创建同步提供程序。例如，如果应用程序包括用于客户联系人跟踪的自定义存储系统，您可以使用简单提供程序或完全自定义提供程序将该数据集成到您的应用程序。&lt;/li&gt;&lt;li&gt;元数据存储服务。此组件包含在 MetaStore21.dll 和Microsoft.Synchronization.MetadataStorage.dll 中。自定义提供程序可以使用该服务作为存储和处理同步元数据的一种便捷方式，特别对于无法存储元数据的副本很适用。元数据存储服务使用占用较小内存和磁盘空间的可靠轻型数据库，可以随提供程序重新分发。该 API 将元数据存储区与用于访问元数据存储区的接口和方法明确区分开，这样既可实现备用存储区，且对提供程序稍作变更即可使用备用存储区。&lt;/li&gt;&lt;li&gt;核心 API 和运行时。这些组件包含在 Synchronization21.dll 和 Microsoft.Synchronization.dll 中。核心API和运行时由除脱机数据库提供程序之外的其他组件使用。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Sync Framework系统架构&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Sync Framework 使用基于提供程序的体系结构。提供程序使其他同步组件不再涉及每个数据存储区的复杂情况和特定实现。这个体系结构配合使用专门的同步元数据，使得 Sync Framework 可以同步编写了提供程序的任何类型的数据存储区。Sync Framework 提供常见数据存储区（如数据库和 NTFS 文件系统）的提供程序，并允许您为其他类型的存储区编写提供程序。提供程序是 Sync Framework 的主要集成点。&lt;/p&gt;&lt;p&gt;下图显示了 Sync Framework 的高级体系结构。同步总是发生在图中所示的两个副本（或&amp;ldquo;节点&amp;rdquo;）之间，但是同步社区（或&amp;ldquo;拓扑&amp;rdquo;）可以为任何形状，如中心辐射型、对等等。除了一些例外情况外，每对参与者可以根据应用程序的要求在 2 层或 n 层体系结构上同步。每个 Sync Framework 组件的文档提供有关相应体系结构和安全注意事项的详细信息。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030809503542.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;图中的元素分为三种类型：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;由开发人员编写的元素。&lt;ul&gt;&lt;li&gt;应用程序根据应用程序的要求调用同步方法、响应事件和处理其他任务。&lt;/li&gt;&lt;li&gt;数据存储区可以是文件系统、关系数据库、平面文件联系人存储区或需要同步的任何其他数据存储区。&lt;/li&gt;&lt;li&gt;数据传输协议确定两个提供程序之间传输数据变更的方式。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;由 Sync Framework 提供的元素。&lt;ul&gt;&lt;li&gt;根据使用的是本机代码还是托管代码，应用程序与同步会话或同步控制器通信，后者与每个同步提供程序通信。&lt;/li&gt;&lt;li&gt;同步运行时驱动同步过程并将状态、冲突和错误信息告知客户端应用程序。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;由开发人员编写或由 Sync Framework 提供的元素，取决于具体实现方案。&lt;ul&gt;&lt;li&gt;提供程序对于正在同步的数据类型而言是特定的。在某些情况下，应用程序需要必须由开发人员编写的自定义提供程序。Sync Framework 提供了很多简化这一过程的 API，还提供了一些组件帮助完成同步最困难的部分（如冲突检测）。&lt;/li&gt;&lt;li&gt;元数据存储区包含元数据，Sync Framework 使用这些元数据确定每个提供程序应选择哪些变更并将它们应用到所服务的数据存储区。存储和使用元数据的方式取决于所使用的提供程序。例如，用于数据库的提供程序一般将元数据存储在数据存储区所在数据库的跟踪表中。对于自定义提供程序，您可以创建元数据存储区或使用随 Sync Framework 提供的服务。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在了解了Sync Framework的核心组件和系统架构之后，我会在下一篇中详细的讨论Sync Framework的另一个关键特征：Sync Metadata，即同步元数据。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2384758.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2384758.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2012/03/06/2382158.html</id><title type="text">Microsoft Sync Framework基础篇 1：Microsoft Sync Framework简介</title><summary type="text">Sync Framework 是一个功能完善的同步平台，实现了应用程序、服务和设备的协作和脱机访问。Sync Framework 提供了一些可支持在脱机状态下漫游、共享数据和获取数据的技术和工具。通过使用 Sync Framework，开发人员可以构建同步生态系统，通过在任意网络上使用任意协议，将任意应用程序与任意存储区中的数据集成在一起。</summary><published>2012-03-06T08:29:00Z</published><updated>2012-03-06T08:29:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2012/03/06/2382158.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2012/03/06/2382158.html"/><content type="html">&lt;p&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;最近，Team接手Microsoft Sync Framework（MSF）相关的开发工作，所以得此良机近距离的研究和学习Microsoft Sync Framework这个优秀的同步工具。当然，第一步自然是学习它的使用方式，下面就是本人学习Microsoft Sync Framework的一系列学习笔记，本着分享学习、共同进步的目的，将系列笔记发于博客园。希望与使用Microsoft Sync Framework的园友共同探讨和学习。初涉同步领域，错误或不当之处，还希望大家不吝指正。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;下面先给出系列随笔的大致目录，在写作过程中会根据需要进行微调。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;目录&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第一部分Microsoft Sync Framework基础&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/06/2382158.html"&gt;Microsoft Sync Framework简介&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2384758.html"&gt;Microsoft Sync Framework架构与运行时&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/08/2385290.html"&gt;Microsoft Sync Framework元数据和同步流程&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第二部分 同步数据库&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387151.html"&gt;同步数据库简介&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/09/2387497.html"&gt;示例：同步 SQL Server 和 SQL Server Compact&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/12/2391945.html"&gt;针对同步进行设置&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第三部分 同步文件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步文件简介&lt;/p&gt;&lt;p&gt;示例&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第四部分 同步Web Feeds&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同步Web Feeds简介&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第五部分使用自定义提供程序&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;自定义提供程序基础&lt;/p&gt;&lt;p&gt;实现简单的自定义提供程序&lt;/p&gt;&lt;p&gt;实现标准的自定义提供程序&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第六部分 Microsoft Sync Framework 4.0 CTP&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;CTP简介&lt;/p&gt;&lt;p&gt;Sync Protocol规范&lt;/p&gt;&lt;p&gt;示例：创建和使用Sync Service&lt;/p&gt;&lt;p&gt;SyncSvcUtil简介&lt;/p&gt;&lt;p&gt;SyncSvcUtilHelper简介&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Microsoft Sync Framework简介&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;引入Microsoft Sync Framework&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步的优点&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在深入学习MSF之前，我们有必要先对同步这个概念来做一个了解，以及为什么同步是必须的。简单来说，同步是保持两个端点/数据存储区中数据一致性的过程。当两个数据存储区中内容完全一致时，我们可以说它们是相互同步的。&lt;/p&gt;&lt;p&gt;比如，如果你想手工同步两个数据库，我们通常会这么做：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;找出源数据库中的变更&lt;/li&gt;&lt;li&gt;把变更发往目标数据库&lt;/li&gt;&lt;li&gt;在目标数据库中应用变更&lt;/li&gt;&lt;li&gt;交换源数据库和目标数据库，重复上述步骤&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;那么，对一个程序，数据存储区或services来讲，我们为何需要为其创建同步机制呢？下面列出了同步最常用的好处：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;离线操作：&lt;/span&gt;&lt;/strong&gt;同步最大的优点就是使我们能够让程序支持离线操作。如果我们为程序创建了同步机制，那么程序用户就可以和本地数据进行交互。直到我们需要从服务器端下载新数据时或者重新获得网络连接时，才使用联网操作。&lt;/p&gt;&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;创建更快速和丰富的用户界面：&lt;/strong&gt;&lt;/span&gt;通过为程序建立同步机制，我们可以创建更加丰富的用户界面，而不用担心程序的性能问题。因为所有的数据通常都从本地获取，所以程序会为我们提供更加迅速的反馈。&lt;/p&gt;&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;降低网络开销：&lt;/strong&gt;&lt;/span&gt;支持同步的程序通常支持上传/下载的增量更新，所以降低了通过网络传输的数据量。&lt;/p&gt;&lt;p&gt;上面只是列出了同步给我们带来的部分好处，现在，我们应该能够了解同步的必要性了。下面我们将讨论如何实现同步。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;实现同步的挑战&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;虽然同步在理论上十分简单，但是，实践起来却十分困难。理解这些问题会让我们更好的了解Microsoft Sync Framework的重要性。具体来说，同步过程中的问题与挑战如下：&lt;/p&gt;&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;错误与失败处理：&lt;/span&gt;设想我们正在同步两个数据库，一个程序错误发生了，比如数据库连接超时或者是往目标数据库应用更改时违反了某个约束，被同步的记录该如何处理呢？&lt;/p&gt;&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;网络失效：&lt;/span&gt;还是上面同步数据库的示例，假如一个数据库在从另一个数据库获取更新时，网络突然失效了，我们该如何应对？&lt;/p&gt;&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;冲突检测：&lt;/span&gt;冲突是指当同一个数据项目同时被同步两端所修改。我们又该如何应对？&lt;/p&gt;&lt;p&gt;显然，我们可以自己书写代码来解决上述的所有问题。但是如果能有一个同步框架能替我们解决所有这些问题，而我们可以专注于实现自己的业务逻辑时，岂不美哉。好了，是时候介绍Microsoft Sync Framework了，Microsoft为我们提供了这个同步框架，不仅内置了解决上述问题的功能，而且可以在任何网络、任何协议中同步两个数据存储区。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;为何选择Microsoft Sync Framework&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Microsoft Sync Framework给我们提供的最大好处在于：它的同步功能支持了数据的离线和在线操作。MSF的主要目的在于允许我们的数据同步集成任何数据源，而不论是何种类型的数据。&lt;/p&gt;&lt;p&gt;让我们先来看看Microsoft对于Microsoft Sync Framework的官方定义：&lt;span style="text-decoration: underline;"&gt;Sync Framework 是一个功能完善的同步平台，实现了应用程序、服务和设备的协作和脱机访问。Sync Framework 提供了一些可支持在脱机状态下漫游、共享数据和获取数据的技术和工具。通过使用 Sync Framework，开发人员可以构建同步生态系统，通过在任意网络上使用任意协议，将任意应用程序与任意存储区中的数据集成在一起。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;下面是Microsoft Sync Framework的一些主要特征：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;独立于底层数据存储、数据类型和协议的强大同步平台&lt;/li&gt;&lt;li&gt;可扩展的提供程序模型&lt;/li&gt;&lt;li&gt;用于同步数据子集的筛选器&lt;/li&gt;&lt;li&gt;内置自动和自定义冲突解决方案&lt;/li&gt;&lt;li&gt;对文件系统、数据库和RSS、Atom feeds的同步支持&lt;/li&gt;&lt;li&gt;支持对等协作方式和客户端-服务器拓扑&lt;/li&gt;&lt;li&gt;为托管代码和非托管代码都提供了API&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Microsoft Sync Framework安装&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Microsoft Sync Framework 2.1&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;目前，Microsoft Sync Framework的最新发布版本是2.1（当然下面即将提到的Sync Framework 4.0 CTP除外），我们可以通过SDK安装包安装开发组件。从 &lt;a href="http://go.microsoft.com/fwlink/?LinkId=194667"&gt;Microsoft Download Center&lt;/a&gt;（Microsoft 下载中心）下载此安装包，按照该网站上提供的安装说明操作。&lt;/p&gt;&lt;p&gt;在 x86 平台上，x86 安装包将会将主要组件安装到 Program Files\Microsoft SDKs\Microsoft Sync Framework\2.1 中，并且将托管 DLL 添加到全局程序集缓存 (GAC)。在 64 位平台上，x86 和 x64 安装包安装到 Program Files (x86)\Microsoft SDKs\Microsoft Sync Framework\2.1 中。&lt;/p&gt;&lt;p&gt;Sync Framework 2.1 包括以下方面的新功能和增强功能：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;数据库提供程序&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;SQL Azure 同步&lt;/li&gt;&lt;li&gt;成批应用变更&lt;/li&gt;&lt;li&gt;基于参数的筛选&lt;/li&gt;&lt;li&gt;删除作用域和模板&lt;/li&gt;&lt;li&gt;升级元数据格式&lt;/li&gt;&lt;li&gt;SQL Server Compact 3.5 SP2 兼容性&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Microsoft Sync Framework 4.0 CTP&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Microsoft Sync Framework 4.0 社区技术预览版(CTP)建立在Sync Framework 2.1之上。实际上，Sync Framework 2.1是安装MSF 4.0 CTP的前提，尽管Sync Framework 4.0的最终发布版本会是一个完整的安装包，不再需要Sync Framework 2.1。&lt;/p&gt;&lt;p&gt;请按以下步骤安装Microsoft Sync Framework 4.0 CTP版本：&lt;/p&gt;&lt;p&gt;1．&amp;nbsp;&amp;nbsp;&amp;nbsp; 安装Microsoft Sync Framework 2.1 SDK，见前一小节，或直接从这里下载：&lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=23217"&gt;http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=23217&lt;/a&gt;&lt;/p&gt;&lt;p&gt;2．&amp;nbsp;&amp;nbsp;&amp;nbsp; 点击以下链接 &lt;a href="mhtml:file://C:\Users\v-zuke\AppData\Local\Microsoft\Windows\Temporary%20Internet%20Files\Content.Outlook\TTILF36N\Download%20Instructions.mht!https://connect.microsoft.com/SQLServer/SelfNomination.aspx?ProgramID=5633&amp;amp;pageType=1"&gt;Sync Framework在线调查&lt;/a&gt; 完成Microsoft关于Sync Framework的在线调查：&lt;/p&gt;&lt;p&gt;3．&amp;nbsp;&amp;nbsp;&amp;nbsp; 一旦你提交了该在线调查，你将会在Microsoft Connect站点看到Sync Framework 4.0 CTP的下载链接:&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2012/243838/2012030616240332.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;Microsoft Sync Framework 4.0 CTP对Sync Framework 2.1进行了扩展，以允许我们针对任何平台来创建脱机应用。在Sync Framework之前的版本中，我们必须使用安装了Sync Framework运行时的Windows系统来作为客户端。而CTP允许Microsoft的其他平台比如Silverlight, Windows Phone 7, 和Windows Mobile, 以及其他的非微软平台如iPhone, Android, 和Blackberry，而不需要为这些平台的客户端安装任何Sync Framework组件，这是因为所有的同步逻辑都从客户端移到了服务端。那么Microsoft Sync Framework 4.0 CTP的这种跨平台能力是如何得到的呢，答案在于它定义了一个新的基于HTTP的同步协议：Sync Protocol。&lt;/p&gt;&lt;p&gt;本系列博客以Sync Framework 2.1为主要目标，当然，对于Microsoft Sync Framework 4.0 CTP我也会在专门的篇章里给予详细介绍。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;一个简单的示例&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;下面这个例子将使用Sync Framework内置的文件同步提供程序来实现两个目录之间的同步。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;新建一个Console Application(控制台应用程序)，名为FileSyncSample。&lt;/li&gt;&lt;li&gt;添加对Microsoft.Synchronization、Microsoft.Synchronization.Files程序集的引用。&lt;/li&gt;&lt;li&gt;修改Main函数为如下格式：&lt;/li&gt;&lt;/ol&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization.Files;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; Microsoft.Synchronization;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt; FileSyncSample&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;   &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;[]   args)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;   Create Source Sync Provider&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            FileSyncProvider   sourceProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; FileSyncProvider(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;C:\TestSync1&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;   Create Target Sync Provider&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            FileSyncProvider   destProvider = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; FileSyncProvider(&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;C:\TestSync2&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;   Create Sync Orchestrator(同步会话)&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            SyncOrchestrator   syncAgent = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SyncOrchestrator();&lt;br /&gt;            syncAgent.LocalProvider =   sourceProvider;&lt;br /&gt;            syncAgent.RemoteProvider =   destProvider;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 开始同步&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            syncAgent.Synchronize();&lt;br /&gt;&lt;br /&gt;            Console.WriteLine(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;同步完成&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/div&gt;&lt;p&gt;上面这个简单的程序就完成了两个目录之间的同步工作，请建立相应的目录和文件来验证它的同步功能吧，相信你会和我一样惊讶于Sync Framework让我们的同步工作变得如此简单，那么让我们一起走进Microsoft Sync Framework的世界吧。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2382158.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2012/03/06/2382158.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html</id><title type="text">LINQ之路系列博客导航</title><summary type="text">本篇提供到LINQ系列之路各篇文章的导航索引</summary><published>2011-12-16T07:34:00Z</published><updated>2011-12-16T07:34:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html"/><content type="html">&lt;!--&lt;style type="text/css"&gt;       h3       {font-size: 16px;padding: 5px 0 0 35px;            height: 35px;            background:  #ffffff url(http://pic002.cnblogs.com/images/2011/243838/2011121420084230.png) top left no-repeat;       }#cnblogs_post_body a   {        padding-left: 10px;background:  #ffffff url(http://pic002.cnblogs.com/images/2011/243838/2011121421452678.png) top left no-repeat;   }&lt;/style&gt;&lt;link rel="stylesheet" href="http://files.cnblogs.com/lifepoem/linq.css" type="text/css" /&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/243838/2011121420084230.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/243838/2011121421452678.gif" alt="" /&gt;&lt;/p&gt;--&gt;&lt;div id="linqNavigation"&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16pt;"&gt;LINQ之路系列博客导航&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;br /&gt;LINQ是.NET Framework 3.5的新特性，其全称是 Language Integrated Query，即语言集成查询，是指将查询功能和语言结合起来。从而为我们提供一种统一的方式，让我们能在C#或VB.NET语言中直接查询和操作各种数据。&lt;/p&gt;&lt;p&gt;本系列文章力图对LINQ进行一个完整和详细的介绍，希望能对广大园友有些许帮助。也期待能和大家一起讨论和学习，共同进步！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第一部分：从这里开始学习LINQ&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本部分包含三篇博客，讨论了LINQ的作用以及C#3.0为LINQ提供的语言特性：隐式类型局部变量、自动属性、匿名类型、扩展方法、Lambda表达式、对象初始化器。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/25/2223765.html"&gt;LINQ之路&amp;nbsp;1：LINQ介绍&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/26/2225054.html"&gt;LINQ之路&amp;nbsp;2：C# 3.0的语言功能（上）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/26/2225086.html"&gt;LINQ之路&amp;nbsp;3：C# 3.0的语言功能（下）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第二部分：LINQ to Objects&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这一部分包含了四篇博客，详细的讲述了LINQ to Objects的方方面面，掌握好这部分内容对于LINQ的学习非常重要，这部分知识也会为LINQ to SQL/Entity Framework和LINQ to XML的学习奠定一个良好的基础。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/27/2226556.html"&gt;LINQ之路 4：LINQ方法语法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/28/2227735.html"&gt;LINQ之路 5：LINQ查询表达式&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/29/2228589.html"&gt;LINQ之路 6：延迟执行(Deferred Execution)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/31/2230175.html"&gt;LINQ之路 7：子查询、创建策略和数据转换&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第三部分：LINQ to SQL/Entity Framework&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;LINQ提供了两个平行的架构：针对本地对象集合的本地查询（local queries），以及针对远程数据源的解释查询（Interpreted queries）。本部分三篇博客先从原理上介绍解释查询，然后对.NET Framework提供的两个解释查询具体实现进行了讨论和学习：LINQ to SQL、Entity Framework(EF)。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/07/2238978.html"&gt;LINQ之路 8：解释查询（Interpreted Queries）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/10/2244386.html"&gt;LINQ之路 9：LINQ to SQL 和 Entity Framework（上）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/15/2249303.html"&gt;LINQ之路10：LINQ to SQL 和 Entity Framework（下）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第四部分：LINQ Operators&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本部分六篇文章中对于LINQ查询运算符（LINQ Operators）进行了完整的介绍，用好它们会让我们的工作更有效率。大家可以按顺序依次对各个LINQ Operators进行学习，也可以把他们作为一个reference，作为参考查询只用。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/16/2250676.html"&gt;LINQ之路11：LINQ Operators之过滤(Filtering)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/18/2253579.html"&gt;LINQ之路12：LINQ Operators之数据转换(Projecting)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/22/2258830.html"&gt;LINQ之路13：LINQ Operators之连接(Joining)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/25/2262646.html"&gt;LINQ之路14：LINQ Operators之排序和分组(Ordering and Grouping)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/28/2265837.html"&gt;LINQ之路15：LINQ Operators之元素运算符、集合方法、量词方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/29/2267243.html"&gt;LINQ之路16：LINQ Operators之集合运算符、Zip操作符、转换方法、生成器方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第五部分：LINQ to XML&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;.NET Framework提供了数种操作XML数据的API。从Framework 3.5开始，最重要的用来处理XML文档的技术当属LINQ to XML。LINQ to XML由一个轻量级的XML文档对象模型和一组补充查询运算符组成，并且，该文档对象模型是LINQ友好的。本部分五篇文章对LINQ to XML进行了详细的介绍。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/06/2277554.html"&gt;LINQ之路17：LINQ to XML之X-DOM介绍&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/07/2278787.html"&gt;LINQ之路18：LINQ to XML之导航和查询&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/09/2281577.html"&gt;LINQ之路19：LINQ to XML之X-DOM更新、和Value属性交互&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/12/2285092.html"&gt;LINQ之路20：LINQ to XML之Documents、Declarations和Namespaces&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/13/2285780.html"&gt;LINQ之路21：LINQ to XML之生成X-DOM（Projecting）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;附录：后记&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;附录包含一篇文章，是我对于本系列博客的一些感想。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/14/2287303.html"&gt;LINQ之路系列博客后记&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2288017.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2011/12/14/2287303.html</id><title type="text">LINQ之路系列博客后记</title><summary type="text">LINQ之路系列博客后记</summary><published>2011-12-14T02:59:00Z</published><updated>2011-12-14T02:59:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2011/12/14/2287303.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2011/12/14/2287303.html"/><content type="html">&lt;p&gt;&lt;strong&gt;缘起&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;今年3月，我换了工作单位。后来多次收到公司的新人培训邮件，不过对此我并不感冒，说实话并不喜欢这种活动。印象中，新人培训无非是唠叨些公司的规章制度、侃述一下公司的光辉历史还有灿烂的未来发展等等。规则制度着实无聊，昨天已经过去，公司的未来看似又很遥远，只有今天是实实在在的。但是，新人培训既不会让我的今天舒服（需要占用一天宝贵的周末时间），也不会double我现在的salary！所以就一推再推，赶在试用期结束之前勉强赴约了。嗯，无奈于人事拿转正相威胁，呵呵。&lt;/p&gt;&lt;p&gt;一天培训下来，虽说也有一部分无聊的&amp;ldquo;照本宣章&amp;rdquo;，但是其中一位讲师的课程内容还是给我留下了深刻的印象。课程内容从IT服务行业概述到企业的文化氛围；从个人职业素养的形成到团队的协作。她的讲学风格非常生动有趣，能够充分调动听者的积极性和注意力，这也在很大程度上改变了我对新人培训此类活动的看法。课程中讲师关于&amp;ldquo;学习之塔&amp;rdquo;的故事则直接激起了我开通个人博客的热情。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;学习之塔&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;学习之塔为我们呈现了不同学习方式之间的效益关系，如下图所示：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/243838/2011121410574767.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;在塔底，是第一种学习方式：阅读。包括为了获得某种知识而进行的书本阅读、互联网查询浏览等。这是最熟悉常见的学习方式，但同时其学习效果却是最低的。&lt;/p&gt;&lt;p&gt;第二种学习方式：听讲，接受培训。&lt;/p&gt;&lt;p&gt;第三种学习方式：向先进者学习。&lt;/p&gt;&lt;p&gt;第四种学习方式：培训辅导他人学习。&lt;/p&gt;&lt;p&gt;最后一种位于塔顶的学习方式：&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;书写日记和博客&lt;/span&gt;&lt;/strong&gt;。这是最有效的学习方式，用心书写的日记和博客能真正强化我们对于生活的感悟，对于学习知识/经验的总结。&lt;/p&gt;&lt;p&gt;可以看出，整个学习之塔，由下至上实际上是一个由被动接受向主动参与转化的过程。参与程度越高，学习效果也越好。但在平时的学习过程中，或许对于学习效率越低的方式，使用得却最为普遍。所以，如何改进我们的学习方式，养成更好的学习习惯，对于最终知识的掌握至关重要。&lt;/p&gt;&lt;p&gt;&lt;em&gt;后来经过搜索，在网上发现了著名的&amp;ldquo;学习金字塔理论&amp;rdquo;，我在新人培训课程中学到的上述&amp;ldquo;学习之塔&amp;rdquo;与其比较相似，有兴趣的朋友可以自己在&lt;/em&gt;&lt;em&gt;google&lt;/em&gt;&lt;em&gt;或&lt;/em&gt;&lt;em&gt;baidu&lt;/em&gt;&lt;em&gt;里面找到相关文章。&lt;/em&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;关于LINQ之路&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;早些时候，公司leader让组里每位同学准备一个知识讲座，以便空时给大家讲授学习。一来可以锻炼各位的讲述能力，要知道，咱们干技术这行的，口语能力不敢恭维的确也大有人在，我自己就是其中之一；二来可以提高大家的专业知识，形成学习的良好氛围。嗯，学习、学习、再学习，这既是咱程序员的宿命，也是咱程序员的乐趣，呵呵。&lt;/p&gt;&lt;p&gt;我选择的讲座topic就是LINQ。原因之一是LINQ作为C# 3.5/4.0里的一项重要技术发布已有些时日了，自己并没有系统的对它进行了解和学习；再者工作中的项目也大都使用了LINQ相关技术，学习好LINQ，对工作也大有脾益。&lt;/p&gt;&lt;p&gt;LINQ之路是我的第一个系列博客，其写作的过程远没有想象中那么有趣和快速，每一篇的完成都花去了我不少的时间和精力。因为对于每一个知识点的讲解，只有建立在充分理解的基础上才可能做好。虽然博客内容大多来自于翻译和总结，但首先我对原文内容进行了认真的学习和理解，对博客中的相关示例进行了实测和注解；其次对相关表述进行了修改整理，使其尽量符合中文的表达习惯。有时候，为了一个词、一句话能得到准确的表达，都得查阅大量的资料：书本、MSDN、还有网页。&lt;/p&gt;&lt;p&gt;上面的学习之塔中，我们已经看到博客是最有效的学习方式之一。当然，必须是用心书写的博客，是自己真正的理解与领悟，而不是简单的复制粘贴再发布。这也是我为何要为LINQ之路系列博客花费这么多精力的原因。我期望能为广大园友提供高质量的文章，就像我期望能读到别人发布的优秀文章一样。所以，通过LINQ之路系列博客，我也是在实践着自己的期望。本着对自己、对大家负责的态度，我尽全力为阅者奉上了LINQ之路。当然，能力有限，疏漏之处，期望得到大家的指正与理解。始终相信：赠人玫瑰，手留余香。我想LINQ之路系列博客的完成，其实最大的受益者还是我自己。在此，&lt;span style="text-decoration: underline;"&gt;我也强烈建议大家能开通自己的博客，把自己的学习经验进行总结，写下来，&lt;/span&gt;&lt;span style="text-decoration: underline;"&gt;share&lt;/span&gt;&lt;span style="text-decoration: underline;"&gt;给大家，让大家一起参与讨论，这样你会学得更好，理解得更加深刻&lt;/span&gt;！这也是本篇后记的目的所在。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;邂逅博客园&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;那是差不多两年前吧，工作中的一个项目用到WCF，于是到处查阅资料。直到发现Artech的WCF之旅、WCF后续之旅，如获至宝。也由此结识了博客园，发现了有这么个网站，专门为了开发者而生。这里有着负责任的编辑、无私的博主、优秀的文章和热情的园友。所有这些让博客园成为了学习、分享和成长的理想场所。从此博客园也成了我经常光顾逗留的地方，理所当然，它也成了我的LINQ之路系列博客的载体。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;感谢&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;看一篇博客容易，而要写一篇博客就没那么容易了。回头看，最容易想到的就是那么多个安静的夜晚，写博客到深夜零点。尽管这是我的第一个系列博客，尽管我的专业和写作水平非常有限，但我确实是用心用力的把它完成了。能有这么多时间来写博客，关键得益于老婆的支持，原因在于写博客的时候，我那10个多月咿呀学语的宝贝女儿就全靠老婆一人照看了。 呵呵，对于我来说，每一篇成功的博客（如果这算成功的话）后面都有一个好女人的支持！老婆辛苦了，谢谢你。当然，享受快乐的同时，还有对女儿深深的歉意，一个好父亲是不该冷落自己的女儿的，何况她那么小。好在，现在终于完成了，我可以好好的陪伴女儿，教他叫&amp;ldquo;爸爸&amp;rdquo;、&amp;ldquo;妈妈&amp;rdquo;，陪她玩、陪她疯了！哈哈，人生如诗。。。&lt;/p&gt;&lt;p&gt;让自己坚持完成本系列博客的，还有广大园友的热情支持和鼓励，谢谢你们。看到自己的文章被你们支持和肯定是一件很开心的事情，没有这些，写出来的博客也不会有任何意义。借次机会，向你们表示真诚的感谢，感谢你们的每一次阅读，每一次评论！&lt;/p&gt;&lt;div id="linqNavigation"&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px;"&gt;系列博客导航：&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="ctl02_TitleUrl" class="postTitle2" href="http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html"&gt;LINQ之路系列博客导航&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/25/2223765.html"&gt;LINQ之路&amp;nbsp;1：LINQ介绍&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/26/2225054.html"&gt;LINQ之路&amp;nbsp;2：C# 3.0的语言功能（上）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/26/2225086.html"&gt;LINQ之路&amp;nbsp;3：C# 3.0的语言功能（下）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/27/2226556.html"&gt;LINQ之路 4：LINQ方法语法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/28/2227735.html"&gt;LINQ之路 5：LINQ查询表达式&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/29/2228589.html"&gt;LINQ之路 6：延迟执行(Deferred Execution)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/31/2230175.html"&gt;LINQ之路 7：子查询、创建策略和数据转换&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/07/2238978.html"&gt;LINQ之路 8：解释查询（Interpreted Queries）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/10/2244386.html"&gt;LINQ之路 9：LINQ to SQL 和 Entity Framework（上）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/15/2249303.html"&gt;LINQ之路10：LINQ to SQL 和 Entity Framework（下）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/16/2250676.html"&gt;LINQ之路11：LINQ Operators之过滤(Filtering)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/18/2253579.html"&gt;LINQ之路12：LINQ Operators之数据转换(Projecting)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/22/2258830.html"&gt;LINQ之路13：LINQ Operators之连接(Joining)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/25/2262646.html"&gt;LINQ之路14：LINQ Operators之排序和分组(Ordering and Grouping)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/28/2265837.html"&gt;LINQ之路15：LINQ Operators之元素运算符、集合方法、量词方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/29/2267243.html"&gt;LINQ之路16：LINQ Operators之集合运算符、Zip操作符、转换方法、生成器方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/06/2277554.html"&gt;LINQ之路17：LINQ to XML之X-DOM介绍&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/07/2278787.html"&gt;LINQ之路18：LINQ to XML之导航和查询&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/09/2281577.html"&gt;LINQ之路19：LINQ to XML之X-DOM更新、和Value属性交互&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/12/2285092.html"&gt;LINQ之路20：LINQ to XML之Documents、Declarations和Namespaces&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/13/2285780.html"&gt;LINQ之路21：LINQ to XML之生成X-DOM（Projecting）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/14/2287303.html"&gt;LINQ之路系列博客后记&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2287303.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/14/2287303.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/lifepoem/archive/2011/12/13/2285780.html</id><title type="text">LINQ之路21：LINQ to XML之生成X-DOM（Projecting）</title><summary type="text">到目前为止，我们已经讨论了如何使用LINQ从一个X-DOM中获取数据。其实，我们同样可以使用LINQ查询来生成一个X-DOM。数据源可以是支持LINQ查询的任何数据，比如：•LINQ to SQL或 Entity Framework查询•本地集合•另外一个X-DOM不管是何种数据源，使用LINQ来产生X-DOM的策略都是一样的：首先写出产生目标X-DOM的函数式构造表达式，然后针对该表达式创建LINQ查询。</summary><published>2011-12-13T03:06:00Z</published><updated>2011-12-13T03:06:00Z</updated><author><name>Life a Poem</name><uri>http://www.cnblogs.com/lifepoem/</uri></author><link rel="alternate" href="http://www.cnblogs.com/lifepoem/archive/2011/12/13/2285780.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/lifepoem/archive/2011/12/13/2285780.html"/><content type="html">&lt;p&gt;到目前为止，我们已经讨论了如何使用LINQ从一个X-DOM中获取数据。其实，&lt;span style="text-decoration: underline;"&gt;我们同样可以使用LINQ查询来生成一个X-DOM&lt;/span&gt;。数据源可以是支持LINQ查询的任何数据，比如：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;LINQ to SQL或 Entity Framework查询&lt;/li&gt;&lt;li&gt;本地集合&lt;/li&gt;&lt;li&gt;另外一个X-DOM&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;不管是何种数据源，&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;使用LINQ来产生X-DOM的策略都是一样的：首先写出产生目标X-DOM的函数式构造表达式，然后针对该表达式创建LINQ查询。&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;比如，假设我们想从数据库中获取customers并产生如下XML：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="1"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Sue&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;3&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           ...&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;我们首先为X-DOM写出函数式构造表达式（这里用简单的字符串值）：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; customers =&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XAttribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #800080;"&gt;1&lt;/span&gt;),&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Sue&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;),&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #800080;"&gt;3&lt;/span&gt;)&lt;br /&gt;                    )&lt;br /&gt;                );&lt;/div&gt;&lt;p&gt;然后我们我们把它放入数据转换之中，创建出针对该表达式的LINQ查询：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; customers =&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; c &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; dataContext.Customers&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XAttribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.ID),&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Name),&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Purchases.Count)&lt;br /&gt;                    )&lt;br /&gt;                );&lt;/div&gt;&lt;p&gt;这里是其结果XML：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="1"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Tom&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;3&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="2"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Harry&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;2&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           ...&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;通过把上面查询的创建分成两步，我们可以更清楚地理解它的工作方式：&lt;/p&gt;&lt;p&gt;第一步：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建一个普通的LINQ to SQL查询，产生一个XElement sequence&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            IEnumerable&amp;lt;XElement&amp;gt; sqlQuery =&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; c &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; dataContext.Customers&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XAttribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.ID),&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Name),&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Purchases.Count)&lt;br /&gt;                    );&lt;/div&gt;&lt;p&gt;第二步：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 创建根元素customers&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; customers = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, sqlQuery);&lt;/div&gt;&lt;p&gt;唯一不同寻常的事情是内容参数sqlQuery，它不是一个简单的XElement，而是IQueryable&amp;lt;XElement&amp;gt;（实现了IEnumerable&amp;lt;XElement&amp;gt;）。还记得X-DOM处理XML内容的过程吗？记住，它会自动遍历实现了IEnumerable的集合。所以，每个XElement都被作为一个子节点被添加到customers元素下。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px; background-color: #c0c0c0;"&gt;排除空元素&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;假如在上面的例子中，我们还想把customer最新的大额purchase包含进来，那么我们可以创建如下查询：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; customers =&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; c &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; dataContext.Customers&lt;br /&gt;                    let lastBigBuy = (&lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; p &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; c.Purchases             &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 子查询获取最新的大额订单&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;                                      &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; p.Price &amp;gt; &lt;span style="color: #800080;"&gt;1000&lt;/span&gt;&lt;br /&gt;                                      &lt;span style="color: #0000ff;"&gt;orderby&lt;/span&gt; p.Date descending&lt;br /&gt;                                      &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; p).FirstOrDefault()&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt;&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XAttribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.ID),&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Name),&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Purchases.Count),&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;lastBigBuy&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;description&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                                    lastBigBuy == &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; ? &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; : lastBigBuy.Description),&lt;br /&gt;                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;price&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                                    lastBigBuy == &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; ? 0m : lastBigBuy.Price)&lt;br /&gt;                            )&lt;br /&gt;                        )&lt;br /&gt;                );&lt;/div&gt;&lt;p&gt;当customer没有大额订单时，上面的查询会产生空的lastBigBuy元素。其实在这种情况下，更好的解决方案是完全忽略lastBigBuy节点。我们可以通过把lastBigBuy元素的构造函数包装在条件运算符中来实现这一目的：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;                    &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt;&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement (&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XAttribute (&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.ID),&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement (&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Name),&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement (&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Purchases.Count),&lt;br /&gt;                            lastBigBuy == &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; ? &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; :&lt;br /&gt;                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement (&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;lastBigBuy&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                                    &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement (&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;description&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, lastBigBuy.Description),&lt;br /&gt;                                    &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement (&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;price&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, lastBigBuy.Price)&lt;br /&gt;                                )&lt;br /&gt;                        )&lt;/div&gt;&lt;p&gt;对于没有lastBigBuy的customers，查询会产生null而不是空的XElement。这正是我们想要的，因为null会被X-DOM简单的忽略掉。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px; background-color: #c0c0c0;"&gt;Stream类型元素&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果我们仅是为了保存(或调用ToString)的目的来产生X-DOM，那么&lt;span style="text-decoration: underline;"&gt;我们可以通过XStreamingElement来改善内存的使用效率&lt;/span&gt;。一个XStreamingElement相当于XElement的简化版本，并且它对子节点应用延迟加载语义。&lt;/p&gt;&lt;p&gt;使用它时，简单的把外层XElements替换成XStreamingElements即可：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; customers =&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XStreamingElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customers&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; c &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; dataContext.Customers&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt;&lt;br /&gt;                        &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XStreamingElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;customer&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XAttribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;id&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.ID),&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Name),&lt;br /&gt;                            &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;buys&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, c.Purchases.Count)&lt;br /&gt;                        )&lt;br /&gt;                );&lt;br /&gt;            customers.Save(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;data.xml&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;/div&gt;&lt;p&gt;直到我们调用Save、ToString或WriteTo方法时，传入XStreamingElement构造函数的查询才会真正被执行。这样就避免了立即把整个X-DOM装载到内存之中。当然另一方面，如果我们多次调用Save，查询也会被重复执行。还有，我们不能遍历XStreamingElement的子节点，它没有提供诸如Elements或Attributes之类的成员。&lt;/p&gt;&lt;p&gt;XStreamingElement不是从XObject（或是其它类）继承而来，它仅有的成员除了Save、ToString和 WriteTo，就是Add方法了，Add方法用于向它添加子节点等内容。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px; background-color: #c0c0c0;"&gt;转换X-DOM&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们可以对现有的X-DOM进行转换。比如，C#编译器和Visual Studio为了描述一个项目，会创建相应的XML文件，该文件会类似以下格式：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Project &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;DefaultTargets&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Build"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; xmlns&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="http://schemas.microsoft.com/dev...&amp;gt;"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;&lt;br /&gt;           &amp;lt;PropertyGroup&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Platform &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Condition&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;=" '$(Platform)' == '' "&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;AnyCPU&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Platform&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductVersion&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;9.0.11209&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProductVersion&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  ...&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Compile &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Include&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ObjectGraph.cs"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Compile &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Include&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Program.cs"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Compile &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Include&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Properties\AssemblyInfo.cs"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Compile &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Include&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Tests\Aggregation.cs"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Compile &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Include&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Tests\Advanced\RecursiveXml.cs"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  ...&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           ...&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Project&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;假如我们现在相对该XML文件进行简化，创建一个只包含相关文件的Report，如下所示：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProjectReport&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;ObjectGraph.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Program.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Properties\AssemblyInfo.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Tests\Aggregation.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Tests\Advanced\RecursiveXml.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProjectReport&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;下面的查询可以完成该项转换：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            XElement project = XElement.Load(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;myProjectFile.csproj&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;);&lt;br /&gt;            XNamespace ns = project.Name.Namespace;                                     &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 获取Namespace&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; query =&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ProjectReport&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; compileItem &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;br /&gt;                        project.Elements(ns + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;).Elements(ns + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Compile&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)     &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 获取所有的Compile元素&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;                    let include = compileItem.Attribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Include&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)                      &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 获取Include属性&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;                    &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; include != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;br /&gt;                    &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, include.Value)                          &lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 转换X-DOM，创建新的File元素&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;                );&lt;/div&gt;&lt;p&gt;查询首先获取所有的ItemGroup元素，然后使用Elements扩展方法获取所有的Compile子元素（结果位于一个平展的sequence之中）。需要注意的是，我们必须指定一个XML命名空间，因为源文件中的所有节点都继承了定义在Project元素上的命名空间，所以单凭一个本地的元素名称如ItemGroup是不够的。之后，我们根据Include属性创建新的元素。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;高级转换&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;但我们对一个本地集合如X-DOM进行查询时，我们可以通过自定义的查询运算符来创建更加复杂的查询，完成更加高级的功能。&lt;/p&gt;&lt;p&gt;假如在前面的例子中，我们想要的是一个按目录分组的层次输出，如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Project&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;ObjectGraph.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Program.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Folder &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Properties"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;AssemblyInfo.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Folder&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Folder &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Tests"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;Aggregation.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Folder &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Advanced"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                         &lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;RecursiveXml.cs&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;File&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                  &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Folder&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Folder&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Project&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;产生这样的结果，我们需要递归的处理路径字符串如： Tests\Advanced\RecursiveXml.cs。下面的方法可以完成这项工作：它接收一个路径sequence，产生我们期望的X-DOM层次结果级：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;        &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; IEnumerable&amp;lt;XElement&amp;gt; ExpandPaths(IEnumerable&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; paths)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; brokenUp = &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; path &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; paths&lt;br /&gt;                           let split = path.Split(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt;[] { &lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;\\&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt; }, &lt;span style="color: #800080;"&gt;2&lt;/span&gt;)&lt;br /&gt;                           &lt;span style="color: #0000ff;"&gt;orderby&lt;/span&gt; split[&lt;span style="color: #800080;"&gt;0&lt;/span&gt;]&lt;br /&gt;                           &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;br /&gt;                           {&lt;br /&gt;                               name = split[&lt;span style="color: #800080;"&gt;0&lt;/span&gt;],&lt;br /&gt;                               remainder = split.ElementAtOrDefault(&lt;span style="color: #800080;"&gt;1&lt;/span&gt;)&lt;br /&gt;                           };&lt;br /&gt; &lt;br /&gt;            IEnumerable&amp;lt;XElement&amp;gt; files = &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; b &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; brokenUp&lt;br /&gt;                                          &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; b.remainder == &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;br /&gt;                                          &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;file&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, b.name);&lt;br /&gt;            IEnumerable&amp;lt;XElement&amp;gt; folders = &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; b &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; brokenUp&lt;br /&gt;                                            &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; b.remainder != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;br /&gt;                                            group b.remainder by b.name into grp&lt;br /&gt;                                            &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;folder&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;,&lt;br /&gt;                                                &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XAttribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;name&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, grp.Key),&lt;br /&gt;                                                ExpandPaths(grp)&lt;br /&gt;                                            );&lt;br /&gt; &lt;br /&gt;            &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; files.Concat(folders);&lt;br /&gt;        }&lt;/div&gt;&lt;p&gt;上面的方法中，第一个查询以第一个反斜线符号把路径分为两部分：name + remainder。比如：Tests\Advanced\RecursiveXml.cs到Tests + Advanced\RecursiveXml.cs。如果remainder为null，则name就是一个文件，files查询会把它装载到files sequence。如果remainder不为null，name就是一个folder，folders查询会处理这种情况。因为其它文件可能也位于相同的目录中，我们必须按目录名来进行分组。对每一个分组，会递归调用该方法来处理子元素。&lt;/p&gt;&lt;p&gt;最终的结果是包含了所有文件和目录的sequence。Concat运算符会保持元素的顺序，所以所有的文件按字母顺序排在前面，然后是按字母顺序排列的所有目录。&lt;/p&gt;&lt;p&gt;有了这个方法，我们可以通过两步来完成我们的查询。首先，获取所有的文件路径：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            IEnumerable&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; paths =&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;from&lt;/span&gt; compileItem &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;br /&gt;                    project.Elements(ns + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ItemGroup&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;).Elements(ns + &lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Compile&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)&lt;br /&gt;                let include = compileItem.Attribute(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Include&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;)&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; include != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;br /&gt;                &lt;span style="color: #0000ff;"&gt;select&lt;/span&gt; include.Value;&lt;/div&gt;&lt;p&gt;然后，在查询中使用ExpandPaths方法来获得最终结果：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;            &lt;span style="color: #0000ff;"&gt;var&lt;/span&gt; query = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; XElement(&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Project&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;, ExpandPaths(paths));&lt;/div&gt;&lt;p&gt;至此，LINQ之路系列博客已经接近完成了。从开始的LINQ介绍到C#3.0的语言特性；从LINQ方法语法到查询表达式语法；从延迟执行到子查询；从解释查询到LINQ to SQL/Entity Framework；从各个查询运算符到LINQ to XML。共计21篇博客，前后历时将近2个月，好漫长的过程，真心感谢各位园友的大力支持和陪伴！稍后，会为大家奉上系列博客后记和全篇博客导航。&lt;/p&gt;&lt;div id="linqNavigation"&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 16px;"&gt;系列博客导航：&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="ctl02_TitleUrl" class="postTitle2" href="http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html"&gt;LINQ之路系列博客导航&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/25/2223765.html"&gt;LINQ之路&amp;nbsp;1：LINQ介绍&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/26/2225054.html"&gt;LINQ之路&amp;nbsp;2：C# 3.0的语言功能（上）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/26/2225086.html"&gt;LINQ之路&amp;nbsp;3：C# 3.0的语言功能（下）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/27/2226556.html"&gt;LINQ之路 4：LINQ方法语法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/28/2227735.html"&gt;LINQ之路 5：LINQ查询表达式&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/29/2228589.html"&gt;LINQ之路 6：延迟执行(Deferred Execution)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/31/2230175.html"&gt;LINQ之路 7：子查询、创建策略和数据转换&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/07/2238978.html"&gt;LINQ之路 8：解释查询（Interpreted Queries）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/10/2244386.html"&gt;LINQ之路 9：LINQ to SQL 和 Entity Framework（上）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/15/2249303.html"&gt;LINQ之路10：LINQ to SQL 和 Entity Framework（下）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/16/2250676.html"&gt;LINQ之路11：LINQ Operators之过滤(Filtering)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/18/2253579.html"&gt;LINQ之路12：LINQ Operators之数据转换(Projecting)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/22/2258830.html"&gt;LINQ之路13：LINQ Operators之连接(Joining)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/25/2262646.html"&gt;LINQ之路14：LINQ Operators之排序和分组(Ordering and Grouping)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/28/2265837.html"&gt;LINQ之路15：LINQ Operators之元素运算符、集合方法、量词方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/11/29/2267243.html"&gt;LINQ之路16：LINQ Operators之集合运算符、Zip操作符、转换方法、生成器方法&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/06/2277554.html"&gt;LINQ之路17：LINQ to XML之X-DOM介绍&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/07/2278787.html"&gt;LINQ之路18：LINQ to XML之导航和查询&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/09/2281577.html"&gt;LINQ之路19：LINQ to XML之X-DOM更新、和Value属性交互&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/12/2285092.html"&gt;LINQ之路20：LINQ to XML之Documents、Declarations和Namespaces&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/13/2285780.html"&gt;LINQ之路21：LINQ to XML之生成X-DOM（Projecting）&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/14/2287303.html"&gt;LINQ之路系列博客后记&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/lifepoem/aggbug/2285780.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/12/13/2285780.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
