在上一篇文章当中,我通过创建一个SnapShot(快照方式)DEMO演示MSF是如何将远程数据
服务器中的数据同步到本地 SQLCE数据库中的。今天这篇文章演示如何使用同步操作向导创建另
外一种方式,即“ 只同步新更改和增量更改”方式。当前这种方式比之前一种"快照方式"要更加便捷,
而且因为快照方式是采用整表同步,因此不管是数据是否被修改过,都是把所有数据下载到本地,
而今天演示的这种方式是只同步修改或新添加的数据,可以说是一种经济实惠的解决方案。
当然,这里并不是说“快照”方式不好,当数据表中的记录频繁变化的话(不稳定)且表中记录
少时,这种方式也是一种不错的方案。另外为了“只同步新更改和增量更改”方式,MSF要在远程数
据服务器上的相应表格中添加相应的字段用于记录数据的修改和添加情况,并且还会新建一个表用
于记录当前表中的记录删除情况(下面会在向导界面中有所体现),而这些都会带来额外的存储开
销,所以我个人认为,当数据表中的记录值变化较小(相对稳定)且表中记录量大时,这种方案会
是一个不错的选择。
好了,开始正文吧。首先要说明的是,如果您看过我的上一篇关于MSF的文章的话,相信您对同步设置向导的整个
流程会有个大体上的了解。今天的这种“只同步新更改和增量更改”只是在其“配置供脱机使用的表”
窗口中进行如下设置(之前流程设置参见上文即可):
![](https://i-blog.csdnimg.cn/blog_migrate/13f24a0def37e26da19748ca50e4de00.gif)
下面解释一下截图中的一些设置,在服务器配置一栏,我们看到有几个下拉列表选项:
“使用下列项比较更新”后面的LastEditDate是我们一会要在远程服务器的dnt_posts1表中建立的一个字段,该字段是日期型,用于记录当前数据行的最后一次修改变时间。
“使用下列项比较插入”后而的CreationDate是该行数据的插入时间。
“将已删除的项移至”后面的dnt_posts_tombstone是当删除该表中的某一行数据时,将该行数据的主键(MSF ADO框架向导要求每个表必须有一个主键,当前表主题为pid).
"使用下列项比较删除"后面的DetetionDate是在dnt_posts_tombstone表中的一列(字段),用于记录当前dnt_posts1表中的记录(主键)删除的时间。
“使用下列项比较插入”后而的CreationDate是该行数据的插入时间。
“将已删除的项移至”后面的dnt_posts_tombstone是当删除该表中的某一行数据时,将该行数据的主键(MSF ADO框架向导要求每个表必须有一个主键,当前表主题为pid).
"使用下列项比较删除"后面的DetetionDate是在dnt_posts_tombstone表中的一列(字段),用于记录当前dnt_posts1表中的记录(主键)删除的时间。
通过上面的设置,系统就会拥有了关于进行数据记录CUD(创建,修改,删除)的时间戳,据此来
作为进行数据同步时的依据。
当完成了“配置数据同步”窗口中的设置之后。如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/d2ab6d893f8e8ae7adc7a2917e34c25e.gif)
这样当我们单击确定时,系统会提示我们如下内容(配置与上一篇文章中SnapShot设置不同):
![](https://i-blog.csdnimg.cn/blog_migrate/7d4a7ddcca9cf044a1103cf5f13bb3b5.gif)
当我们再次点击确定时,系统开始将本地数据库(本DEMO为BiDirectSynce#2.sdf)与远程数据库
进行同步,如下:
![](https://i-blog.csdnimg.cn/blog_migrate/1bbdcea3db929078bdb50beef1caa052.gif)
然后接下来的操作与之前的SnapShot方式一样,也是对要同步的数据表做进一步的设置(使用表中
的哪些字段等)。然后输入DataSet名称并点击“完成”按钮即完成了向导设置工作。
接下来就是在相应的WinForm中显示同步的数据了,在这里我偷了个懒,只是将前文中的窗体“复制”
了一份,重命名为BiDirectForm。当前同步的代码与前文也是一样的。这里就不多做介绍了。下面继续
们的内容。
因为设计器完成时给我们生成的代码都是从服务器端向本地同步数据的。而如果本地数据编辑修改
之后,要如何同步(上传)到远程服务器上面呢。其实, MSF在这方面封装的非常好,我们只要通过下
面的代码即可以完成将本地的数据同步到远程,如下:
//
首先是将修改的数据先保存到本地SDF数据文件中
SnapDatasView.EndEdit();
// 下面更新方法"Update"被重载5次,分别提供了datarow,datarow[],dataset,object[]等类型参数
this .dnt_post1TableAdapter.Update( this .biDirectSynceDataSet.dnt_posts1);
this .dnt_post1TableAdapter.Dispose();
// 然后是将本地数据同步到远程数据服务器
BiDirectSyncDataSyncAgent SyncAgent = new BiDirectSyncDataSyncAgent();
SyncAgent.dnt_posts1.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
SyncAgent.Synchronize();
SnapDatasView.EndEdit();
// 下面更新方法"Update"被重载5次,分别提供了datarow,datarow[],dataset,object[]等类型参数
this .dnt_post1TableAdapter.Update( this .biDirectSynceDataSet.dnt_posts1);
this .dnt_post1TableAdapter.Dispose();
// 然后是将本地数据同步到远程数据服务器
BiDirectSyncDataSyncAgent SyncAgent = new BiDirectSyncDataSyncAgent();
SyncAgent.dnt_posts1.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
SyncAgent.Synchronize();
上面代码中的SyncDirection可谓至关重要,在前文中我曾说过,MSF做数据同步时有四种方式,依
次是(这里只为加深印象):
Bidirectional:首次同步期间,客户端通常从服务器下载架构和一个初始数据集。执行后续同步时,客户端将更改上载到服务器,然后从服务器下载更改(本文演示) 。
DownloadOnly: 首次同步期间,客户端通常从服务器下载架构和一个初始数据集。执行后续同步时,客户端从服务器下载更改。
Snapshot: 客户端将从服务器下载一个数据集。每次同步期间,这些数据都将完全刷新。
UploadOnly: 首次同步期间,客户端通常从服务器下载架构。执行后续同步时,客户端将更改上载到服务器。
DownloadOnly: 首次同步期间,客户端通常从服务器下载架构和一个初始数据集。执行后续同步时,客户端从服务器下载更改。
Snapshot: 客户端将从服务器下载一个数据集。每次同步期间,这些数据都将完全刷新。
UploadOnly: 首次同步期间,客户端通常从服务器下载架构。执行后续同步时,客户端将更改上载到服务器。
因为MSF设计器默认是Snapshot方式,所以是不支持同步(上传)远程的。所以我们这里使用了
Bidirectional(双向同步),这样我们先将本地修改的数据上传到远程之后,再将远程上的数据修改下
载到本地。
整个操作流程是这样的(首先在本地修改变相应数据):
![](https://i-blog.csdnimg.cn/blog_migrate/7ab74e59db8e222cf57dd38e7befae43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1e8ce866d8e093892b66fdf7f5ca4cbd.gif)
然后同步到远程数据服务器上:
当然如果此时远程服务器上有一行记录(注:与本地修改的记录不是同一主键pid),这条记录的修
改值也会同步到本地数据文件(sdf)中。
有经验的朋友看到这里会发现一个问题,就是假设如果我在本地修改某一数据行时,此时在远程数
据库中有一个用户也在修改相同的一行数据(同一个主键pid)。那当我们进行从本地向远程的双向同步
时,最终下载到本地数据文件中的远程数据会是那个值呢?
其中这里MSF的判断是以 优先级来决定最终使用那一方的数据的。而优先级毫无一问是远程数据优
先级要高。所以最终我们在本地修改的数据会被远程修改的数据所“ 覆盖”。MSF默认是这样的,但如果
我们就是想让本地的优先级要大于远程,换句话说就是想用本地数据“覆盖”远程的相同主键相同字段
值的时候,该如何办呢?
其实这里有一个很BT的方式,就是手工修改MSF为我们生成的相关应文件。在本DEMO中,我们修改的
是BiDirectSyncData.Designer.cs文件中的这一行(line 189)代码,原文如下:
this
.UpdateCommand.CommandText
=
@"
UPDATE dbo.dnt_posts1 SET [fid] = @fid, [tid] = @tid,
[parentid] = @parentid, [layer] = @layer, [poster] = @poster, [posterid] = @posterid,
[title] = @title, [postdatetime] = @postdatetime, [message] = @message, [ip] = @ip,
[lastedit] = @lastedit, [invisible] = @invisible, [usesig] = @usesig, [htmlon] = @htmlon,
[smileyoff] = @smileyoff, [parseurloff] = @parseurloff, [bbcodeoff] = @bbcodeoff,
[attachment] = @attachment, [rate] = @rate, [ratetimes] = @ratetimes, [LastEditDate] = @LastEditDate,
[CreationDate] = @CreationDate WHERE ([pid] = @pid) AND
(@sync_force_write = 1 OR ([LastEditDate] <= @sync_last_received_anchor))
SET @sync_row_count = @@rowcount " ;
[parentid] = @parentid, [layer] = @layer, [poster] = @poster, [posterid] = @posterid,
[title] = @title, [postdatetime] = @postdatetime, [message] = @message, [ip] = @ip,
[lastedit] = @lastedit, [invisible] = @invisible, [usesig] = @usesig, [htmlon] = @htmlon,
[smileyoff] = @smileyoff, [parseurloff] = @parseurloff, [bbcodeoff] = @bbcodeoff,
[attachment] = @attachment, [rate] = @rate, [ratetimes] = @ratetimes, [LastEditDate] = @LastEditDate,
[CreationDate] = @CreationDate WHERE ([pid] = @pid) AND
(@sync_force_write = 1 OR ([LastEditDate] <= @sync_last_received_anchor))
SET @sync_row_count = @@rowcount " ;
大家看到没有,在上面的SQL语句中有这样一段内容(倒数第二行):
(@sync_force_write
=
1
OR ([LastEditDate]
<=
@sync_last_received_anchor))
我们只要将@sync_force_write修改为1(让条件永远为真),或干脆将这段内容全部删除。这样
就会将我们本地的修改全部提交到远程数据库中并最终完成对数据库中相同数据行的覆盖。
好了,今天的内容就先到这里了。在下一篇文章中,我会分析一下设计器向导为我们所生成的文件,
里面的大部分类都对应着我之前所说的这张图中的内容,如下:
![](http://daizhj.cnblogs.com/images/cnblogs_com/daizhj/ado.net_sync_archieve.gif)
而为什么要分析的原因在上面我们已看到了,通过修改这些文件中的相应内容,会满足我们开发中
所面对的问题和需求。当然我这里并不是建议大家去频繁修改这些文件,因为这些文件都是代码生成器
“生成的”。如果冒然修改很可能会出现当设计器配置属性等发生变化时,导致我们的修改被“覆盖”,这
样我们修改的代码就白写了。但了解这些文件对于我们了解MSF中的Ado.NET支持真的很有帮助,希
望大家理解。
另外下一篇文章也会简单对比一下SnapShot与本文中所说的“ 只同步新更改和增量更改”在具体
生成文件上的一些差异。可以说正是这些差异导致了这两种方式的不同。
原文链接:http://www.cnblogs.com/daizhj/archive/2008/11/17/1334804.html
作者: daizhj, 代震军
Tags: 微软同步框架,ado.net,sqlce
网址: http://daizhj.cnblogs.com/
下载链接,请点击这里:)