AppleSeeker's Tech Blog
Welcome to AppleSeeker's space
在服务器和智能客户端的数据同步功能相信很多人会使用到,虽然Smart Client Software Factory已经内置了离线功能,但是对于数据同步的支持太单薄,好在微软已经为我们考虑到了,ADO.NET Sync Services的出现提供一种新的模式来改善原先的不足。

在客户端PC或者智能设备本地存储数据的优势是明显的:
本地数据缓存,提供离线(offline)支持; 合理利用客户机的处理能力,提升系统响应速度; 减小服务器端应用服务器和数据服务器的压力; 适合偶尔连接的应用 OCA(Occasionally Connected Application )。

这种系统最令人头疼的问题就是“数据同步”问题。“数据同步”问题是必须解决的问题,也是必须开发的功能。然而,数据同步并不是用户需求。微软曾推出两种数据方案:远程数据访问(RDA), 合并复制(Merge replication),这两种方案主要用于以数据库作为数据源的数据同步,并且不是特别灵活,不能解决很多遗留系统问题。

ADO.NET Sync Services三个组成部分:运行时(runtime),元数据服务(Metadata Services),提供者(Provider)
ADO.NET Sync Services的好处在于:
1.提供Provider 模式,允许开发人员自定义提供者(Provider)以实现任意数据源之间的同步。
2.使得开发者关注同步运行时(Sync Runtime)
3.同步数据时不需要Replicating数据库
4.组件化,SOA架构,可以使用Web Service及WCF

ADO.NET Sync Services For Device就是为了在移动设备上同步数据提供了解决方案。

主要对比 RDA 合并复制 Synchornization  Services
使用服务进行同步
支持异类数据库
跟踪增量更改
冲突检测与解决
在客户端轻松建立视图
自动初始化架构和数据
支持大型数据集
可在本地使用查询分析器
自动传播架构更改
在设备上使用

Sync Service提供4种同步的方式:仅下载同步、仅上传同步、双向同步、快照同步。
可以根据不同的场景需求来选择不同的同步方式。

在下面的Demo中,将详细叙述。

首先,从桌面的Client来了解下Sync Service,MS提供了很便捷的方式来快速实现。
创建一个WindosForm的Client程序。

在界面上添加一些控件,做一个简单的数据绑定效果。运行后程序如下

在工程中添加LocalDataCache文件。添加完后,会提示你同步操作。

选择好连接的源数据库,选择好新建的Client数据库。在高级中,选择创建的组件,你可以选择创建客户端和服务器端2端的组件。也可以只创建客户端或服务器端的。系统会根据你的选择来自动创建生成同步Provider,Agent等。选择完后,在左侧选择同步的数据库。

在客户端,一旦系统自动生成组件后,会自动创建一个sdf数据库,用户在本地保存数据,然后与服务器的数据库进行同步。
在左侧选中一个数据库后,则会出现一些规则。比如insert时比较哪个字段,update时比较哪个字段等。

配置完后,会在工程中生成一个.sync文件。
同步操作代码很简单,只需要2行即可。

1MyDBLocalDataCacheSyncAgent syncAgent = new MyDBLocalDataCacheSyncAgent();
2Microsoft.Synchronization.Data.SyncStatistics syncStats = syncAgent.Synchronize();
syncAgent--代理类。只需调用代理类的同步方法即可实现同步。当然啦,如果你想选择同步的方式的话。还需要添加代理类中,某个表的同步方式。
1syncAgent.Books.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
这时,我指定的是双向同步。
一个简单的同步应用就完成了。很便捷吧。

下一个Demo,将演示如何实现使用WCF来实现同步。
这里将先创建一个WinFrom程序作为Client端,创建一个WCF Service作为服务器端。

同样在添加LocalDataCache文件时,必须选择客户端和服务器端的组件,这时,将服务器端选择WcfService工程即可。

此时,在Client工程中除了有.sync文件,还有.Client.sync文件,该文件配置了客户端的Provider等信息。服务器端则为.Server.sync文件。
同步方式一致。

下一个Demo,演示如何使用Web Site方式提供同步服务。微软这个组件,只能自动生成工程文件,但无法在WebSite中生成。只能通过手写一些代码来完成。其实效果一样,这样对于Sync Service的原理,应该更能理解。这里的Demo将演示Web Service。
在Web Site中,需要实现几个类。
当然啦,Service中的公开方法必不可少。另外还需要添加实现SyncAdapter的表的SyncAdapter。该adapter将对数据库表进行添、删、改的操作。并且可以自己实现这些Command语句、参数及当同步冲突时,采取你自定义的解决方法。
帖一段代码:当添加时,该如何实现。
 1        // BooksSyncTableInsertCommand command.
 2        this.InsertCommand = new System.Data.SqlClient.SqlCommand();
 3        this.InsertCommand.CommandText = @" SET IDENTITY_INSERT dbo.Books ON INSERT INTO dbo.Books ([SysNo], [BookName], [CSBN], [AuthorSysNo], [PublishTime], [LastEditDate], [CreationDate]) VALUES (@SysNo, @BookName, @CSBN, @AuthorSysNo, @PublishTime, @LastEditDate, @CreationDate) SET @sync_row_count = @@rowcount SET IDENTITY_INSERT dbo.Books OFF "
;
 4        this.InsertCommand.CommandType =
 System.Data.CommandType.Text;
 5        this.InsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("@SysNo"
, System.Data.SqlDbType.Int));
 6        this.InsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("@BookName"
, System.Data.SqlDbType.NVarChar));
 7        this.InsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("@CSBN"
, System.Data.SqlDbType.NVarChar));
 8        this.InsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("@AuthorSysNo"
, System.Data.SqlDbType.Int));
 9        this.InsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("@PublishTime"
, System.Data.SqlDbType.DateTime));
10        this.InsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("@LastEditDate"
, System.Data.SqlDbType.DateTime));
11        this.InsertCommand.Parameters.Add(new System.Data.SqlClient.SqlParameter("@CreationDate"
, System.Data.SqlDbType.DateTime));
12        System.Data.SqlClient.SqlParameter insertcommand_sync_row_countParameter = new System.Data.SqlClient.SqlParameter("@sync_row_count"
, System.Data.SqlDbType.Int);
13        insertcommand_sync_row_countParameter.Direction =
 System.Data.ParameterDirection.Output;
14        this.InsertCommand.Parameters.Add(insertcommand_sync_row_countParameter);

还需要添加一个ServerSyncProvider继承DbServerSyncProvider。当同步时,会调用该Provider。通过Provider来操作Adapter。
当然,该Provider还提供一些事件,比如当冲突发生时,可以自定义解决方法。ApplyChangeFailed。在冲突发生后,可以取到两边的冲突数据。
 1    private void OnInitialized()
 2    
{
 3        this.ApplyChangeFailed += new EventHandler<Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs>
(MyDBLocalDataCacheServerSyncProvider_ApplyChangeFailed);
 4    }

 5
 6    void MyDBLocalDataCacheServerSyncProvider_ApplyChangeFailed(object
 sender, Microsoft.Synchronization.Data.ApplyChangeFailedEventArgs e)
 7    
{
 8        System.Data.DataTable dtS =
 e.Conflict.ServerChange;
 9        System.Data.DataTable dtC =
 e.Conflict.ClientChange;
10

11        System.Console.WriteLine("ss"
);
12    }

在实现Web Service来同步数据时,需注意,在客户端添加Web引用时,需主要要修改生成的代理类中的一些地方。
注释掉系统自动生成的SyncGroupMetadata等类,改用调用Sync Service的dll中的。不然在同步时,会因为这些而出错。
当然啦,这些提供了同步时的扩展信息。目前,我还没有具体研究。

最后一个Demo,就是在Device中使用同步。
界面很简单。
最初启动后,数据库中没有记录,所以Load Data后,没有数据。

在同步数据后,数据就会保存到数据库中,再次Load Data后,本地数据库中就已存放数据了。


在Device中,使用本地数据库时,注意连接字符串的设置:应使用比如
1this.ConnectionString = @"Data Source= \Program Files\DeviceClient\MyDB.sdf";
不支持|DataDirectory|这种方式。

总结:
Sync Services的出现,大大改善了在数据同步,使得我们可以更好的来关注致力于应用层面上。相信未来Sync Services还会有更好的改变。

在本文中,为什么使用Web Service而不是WCF的原因呢,在于Sync Services不能自动生成Web Site上的代码。
通过手写一些代码,能够了解Sync Services的很多实现细节。

参考:
张欣的WebCast--《移动数据访问新手段--ADO.NET Sync Services for device简介》
JustDI--《话说微软刚出的同步框架Sync Services》

代码下载:Sync_Solution.rar
项目DB下载:Sync_DB.rar

Author:AppleSeeker
Date:2008-07-18
posted on 2008-07-18 13:39  AppleSeeker(冯峰)  阅读(3722)  评论(21编辑  收藏  举报