Synchronization N层 使用WebService同步SQLCompact
使用Synchronization做与web service进行数据库同步。
Sync同步非常强大,可以同步不同地点的数据库中的数据。
说明:本案例使用微软的经典数据库示例NorthWind,数据库系统使用 MSSQL Express
步骤:
1.使用VS2010 SP1创建新解决方案:"DataBase Sync MSSQL Express And SQLCompact N-Tier With WebService" 并创建windows项目"WindowsClient"
2.将From1更名为"SyncClientDemoFrm",并将其Text属性修改为" SyncClientMainFrm"。
3.在解决方案中添加新的windows 类库项目,取名为"SyncServerProvider"。该项目用作服务器端的同步提供程序,以便将来的web Service能够将数据传递到数据库中进行同步。
4.删除SyncServerProvider项目中的Class1.cs文件。
5.在WindowsClient项目中添加新项,在添加新项对话框中选择"本地数据库缓存"模板,取名为NorthwindLocalDataCache.sync
6.在上一步点击确定后会弹出"配置数据同步对话框"
在该对话框中"数据库连接"选项组中的"服务器连接"选择"新建"。弹出"添加连接"对话框这里创建好到数据库的连接。本案例中的数据是 SQL Server Express 版本,服务器名略有不同。
点击确定之后会回到"配置数据同步"对话框。此时数据库连接已经配置有一些了。如同所示:
在该对话框中左下角点击"添加按钮",弹出"配置供脱机使用的表"对话框。
该对话框显示的都是数据库服务器中Northwind数据库的所有表。这里选择你要进行同步的数据库表就可以了,我这里不做全选,只做一个表的同步示例,所以此处选择Employees表。当选中标之后,右边会有对应的选择项出现。如图所示:
这里逐项解释一下:
要下载的数据的意思是:每次同步的时候是怎么个同步法。第一项是第一次同步全部之后,以后的同步只同步有更新的和新添加的或者删除掉的。第二项是每次都同步更新整个表格的数据,不论是新增的、修改的、删除掉的。这里我们选择第一项默认的。
使用下列项比较更新的意思是:通过数据库表中哪个字段来进行比较数据库中的数据是否有更新,如果你有自己定制的话,可以使用自己定制的,选择新建配置就好了。我这里没有进行单独的配置,所以使用默认的就可以了。
这两个选项的意思和上面的选项意思是一样的,分别用作于数据库表格数据有新增和删除的时候处理项。删除的时候需要将以前删除的数据移动到一个备份表中去,所以这里会新建一个Employees_Tombstone表,将客户端删除的数据都移动到此表中,方便日后同步的时候与服务器的数据进行比较。
这些选项我都不做修改,直接使用默认的就可以了。
点击确定后会回到"配置数同步"对话框中,此时左边缓存的表中多了Employees了。
在右边有个"高级"下拉面板,展开它,如图所示:
此处会给我们的代码创建同步的组件。由于本案例要演示N层的同步,所以此处是关键点。
修改"服务器项目位置",本来其默认位置是WindowsClient项目中,那样的话就成了两层形式的同步了。所以此处我们要将其修改为SyncServerProvider。
客户端位置不动,还是在windowsClient,当然,如果你有特殊的操作,那么是可以将其创建到其它位置中去的。
此时"配置数据同步"对话框的操作基本完成,点击确定按钮。此时弹出一个"生成SQL脚本"对话框。因为同步的配置里面配置了我们如何与数据库中的表进行同步,同步的时候需要很多的辅助表和字段,这样我们才能很好的同步,这个对话框的意思就是那些辅助表和字段是否自动创建好脚本,一边我们日后使用。当然打勾确定了!
7.点击上个"生成SQL脚本"对话框中的确定按钮,稍等片刻之后,会弹出一个"数据源配置向导".
此处配置的数据源是指客户端连接客户端Compact数据库的数据源。这里为了案例上面的方便,选择数据集,点击下一步。
选择数据库连接,默认使用了之前配置好的数据库连接
点击下一步,到"选择数据库对象",展开表,选择里面的Employees表。其它的三个表,是Sync同步框架生成的辅助表,没有必要选择。
点击完成。OK同步配置已经完成,并且在windowsClient里面添加了几个引用。如图:
同时也在SyncServerProvider项目里面添加了引用,如图:
此处需要注意的是这些引用添加的版本问题。如果你没有额外安装Sync Framework或者SDK的话,这里用的就是系统默认的版本。如果你安装了额外的版本或者sdk的话,那么这里有可能会出现一些冲突问题。那么我建议你把这些引用删除掉,然后重新添加对应相同版本的引用,这样就可以避免错误。
本案例使用Sync Framework的版本是2.1 。如图所示:
System.Data.SqlServerCe 的版本是3.5.1.0 。
为了以后方便在其它环境中打开,不至于出现版本问题,这里修改了每个引用的属性"复制本地"为True如图:
两个项目的properties里面都添加了Settings.settings文件,里面都是包含各自的数据库连接字符串。
在windowsClient项目中也添加了两个SQL脚本文件夹。这个你可以打开看看,这里不做说明了。
同时还有NorthwindLocalDataCache.Sync、NORTHWND.sdf、NORTHWNDDataSet.xsd这三个文件。分别是客户端同步配置,客户端Compact数据库,以及连接该数据库的类型化数据集。
在SyncServerProvider项目中生成了两个文件,如图:
分别是服务器端的同步配置文件,以及服务器端的同步契约。这个契约文件可以用作于WCF,主要提供了一个契约接口,提供同步功能。该类在本案例中基本上,没有太多的作用了,因为,我们会自己通过web service来实现这个契约。(该类可删除不要)
8.在解决方案中添加新的项目,使用Web 服务模板,并取名字为SyncWebService。如图所示:
在项目SyncWebService项目中删除自动添加出来的Service1.asmx文件。在项目中添加新项,选择Web服务,取名字叫SyncWebServiceProvider.asmx
删除该服务中的默认的helloWord方法。
给该项目添加引用,选择项目选项卡中的SyncServerProvider项目,如图所示:
9.编写该服务的代码。
在SyncWebService.asmx.cs添加ServerSyncProvider的引用。
然后编写4个方法分别是ApplyChanges、GetChanges、GetSchema、GetServerInfo。代码与之前创建的SyncServerProvider项目中自动生成的NorthwindLocalDataCache.Server.SyncContract.cs文件中的NorthwindLocalDataCacheSyncService 的代码基本一致。如果你之前没有删除掉这个方法的话,呵呵,你舒服了,可以直接将这个类中的代码拷贝到SyncWebService.asmx.cs中。当然拷贝之后还得做点小修改。
拷贝之后,一堆错误,第一个就是构造函数名称,修改为服务类的名称。
该项目没有引用Sync Framework所以很类没有,添加SyncFramework的引用。
之后,在类文件中添加引用。OK没有发生错误了。
修改每个方法上面的特性标记。删除原来的[System.Diagnostics.DebuggerNonUserCodeAttribute()]
特性,添加特性标记[WebMethod]。OK现在服务这里大功告成!
10.编写客户端的Web服务引用代码,此处一定要注意,平常我们可以直接添加Web服务引用就可以了,但是这里绝对不能直接添加Web服务引用,因为如果是这么做的话,将来会导致数据类型出现强制转换的错误。
在WindowsClient项目中添加新项,选择类并取名叫RemoteWebServiceRef.cs。
在该类中添加引用如图所示:
该类实现继承System.Web.Services.Protocols.SoapHttpClientProtocol 类,该类用于使用SOAP协议访问Web服务的代理。添加这个RemoteWebServiceRef的构造函数,带参数url,用于将来在外面通过指定web服务的url地址让这个类来实现代理。在这个类中实现4个方法,分别是ApplyChanges、GetChanges、GetSchema、GetServerInfo。这四个方法是对应web服务中要调用的四个方法,也就是sync同步实现的提供程序。
ApplyChanges方法的详细代码如下:
1 /// <summary>
2 /// 同步的应用更改
3 /// (该方法将使用Document格式向SOAP发送消息,请求web服务)
4 /// </summary>
5 /// <param name="groupMetadata">同步组的元素据</param>
6 /// <param name="dataSet">同步数据集</param>
7 /// <param name="syncSession">同步会话</param>
8 /// <returns>同步上下文</returns>
9 [System.Web.Services.Protocols.SoapDocumentMethod(Action = "http://tempuri.org/ApplyChanges", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
10 public SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession)
11 {
12 object[] result = this.Invoke("ApplyChanges", new object[] {
13 groupMetadata,
14 dataSet,
15 syncSession
16 });
17 return (SyncContext)result[0];
18 }
通过这个方法里面的代码可以实现使用SOAP的形式调用web服务而不会出现类型强制转换的问题。
其它三个方法基本类似,具体请参看案例的源代码内容。
11.实现客户端的服务器同步代理提供程序类的代码。
在windowsClient项目中添加新类取名叫ServerSyncProviderProxy并且继承自Microsoft.Synchronization.Data.ServerSyncProvider。这个类主要用作于将来在客户端上面调用远程的同步提供程序。
在该类里面声明RemoteWebServiceRef类型的字段,取名叫remoteService。
在该类中创建ServerSyncProviderProxy的构造函数,带url参数。用于指定RemoteWebServiceRef的url参数。
在该类中实现Microsoft.Synchronization.Data.ServerSyncProvider中的ApplyChanges、GetChanges、GetSchema、GetServerInfo 这4个方法的重写。并且在其重写的代码中调用字段remoteService的对应的这4个方法,这样就将本地的服务器同步提供程序代理与远程web服务相对应起来了。
并且,在这个类中还要实现dispose方法,否则会报错误。
至此为止,服务器的同步提供程序代理类也编写好了。剩下的工作就是开始编写客户端的同步调用代码了。
12.打开WindowsClient项目中的SyncClientDemoFrm窗体。在菜单栏中打开"数据"->"显示数据源"。在"数据源"面板中选择到NORTHWNDDataSet下面的Employees,在下拉列表中选择"详细信息"。
此时这个Employees拖放出来的时候就会变成详细信息显示了。
将EmpLoyees从"数据源"面板中拖放到SyncClientDemoFrm窗体中。窗体由一片空白变为了有显示Employees的详细信息的窗体了。当然我这里这么做是因为这样简单,本案例的重点不在于如何显示数据,在于数据的同步,所以这里使用这种最简单的方式来做,这也是当初在选择创建数据源的时候选择创建的是"DataSet"而不是"实体数据模型"的原因所在。现在界面效果如图所示:
当然么做它会自动给我生成好客户端到Compact数据库添删改查的所有代码。
界面基本上就做的差不多了。
13.实现到服务器的同步代码。
在界面的工具栏中添加一个新的按钮。给它取名字叫tsbSyncServer。如图所示:
双击它生成他的Click事件。
在该类中分别声明出这几个字段,如图所示:
在该类中添加InitSync方法来初始化同步的一些参数。如图所示:
提醒注意:这里的url路径是我的web服务器运行的路径,肯定每个运行的url都会有区别的,请适当修改!
看见没。。。竟然同名,我晕,之前没有意识到这个问题存在。不过也没关系,只是访问的时候必须加上命名空间,否则就报错,麻烦了点。
还有一个重要的错误就是忘记在这个项目中添加另一引用了,就是:
这个,没有它的话,是不能使用DbServerSyncProvider这个类的。这里加上它。
OK,接着继续。这个初始化方法,每行代码都在注释中详细说明了。在下面我们还生成了remoteProvider.ApplyChangeFailed事件的处理程序。当遇到同步异常的时候,可以通过这个异常处理程序来补救,当然,我们这里不做别的什么事情,只是把异常显示出来。
写完这个InitSync方法之后,当然要在窗体加载事件中调用了,否则。。。。
14.回到这个tsbSyncServer工具按钮的事件中,来添加同步处理代码。
有了上面13步所编写的代码,只要在这个事件中编写一句话就可以实现同步了。syncAgent.Synchronize();
但是同步之后是应该有些信息的,所以之前定义了的syncStats字段就可接收上面的Synchronize方法所返回的同步状态信息了,之后我们可以通过这个syncStats字段来显示出同步的一些信息。
当然同步了之后是要在客户端界面刷新数据的,不然界面是不会及时显示出消息内容。只要调用EmployeesTableAdapter来重新填充一下数据就可以了。
这个事件里面的代码如下所示:
15.编译一下,一切OK!运行吧,试试能否成功。我的运行没问题。
16.至此为止,如何通过N层的形式来完成Sync Framework的同步功能,这个案例一步一步就做完了。
代码和步骤走了一遍,但原理又是什么呢?请看下面的图示
此图来源MSDN《如何配置N层同步》。
现在将我们所写的代码一一与这幅图对应一下:
三个项目,用红色框起来了。关键的类,对应于这个N层架构图中的组件。
虽然本案例是使用windows的应用程序,但是抛开界面不谈,那么这个案例是可以应用于其它的UI场合的。
例如可以将这里的WIndows应用程序更换为WinCE的。Sync部分的代码是没有任何变化。
当然不同的数据库同样实现N层同步的代码基本上是一致的,你可以参照这个例子做SQL Server To SQL Server 或者 SQL Server To SQL Compact 等不同数据库之间的N层同步,没有什么太大的差别。
举一反三。