好的.Net同步框架适用于n层架构

3
对于一个项目,我需要改变服务器和客户端之间的通信方式。
实际上这是一个WCF服务,在控制台应用程序中托管,将整个表内容发送到客户端,客户端用新内容替换其所有本地缓存。
客户端应用程序可以离线工作(我们有一个本地缓存,通过磁盘序列化持久化,还有一个事务列表,存储所有需要在连接后发送到服务器的更改)。
问题在于,现在这个同步将在GSM连接上发生,发送整个表内容真的非常耗费资源。
因此,要么我自己实现所有这些(设置修改日期、存储上次同步日期、获取仅更新的字段、更新我的缓存),要么我可以找到一种标准方法来实现它。我认为专门的库会做得更好,因为他们已经想到了很多情况,我肯定没有想到。
同步层具有低耦合性,所以改变它的工作方式并不是什么大问题。
我的项目需求是:
  • 应该具有增量同步
  • 可以将更改推送到服务器
  • 离线访问/存储信息
  • 可能需要进行完全重新同步(损坏的缓存或新计算机)
  • 服务器端的数据提供程序是Entity Framework
  • 我需要重用我的当前自定义身份验证
  • 额外加分:某些类型具有特殊的同步(例如,我有一个包含小文件的数据库,但在客户端上,文件必须直接放在文件夹中)
我已经找了一些现成的解决方案。
我发现了一些关于Microsoft Sync Framework的东西,但它似乎非常ADO.Net导向,我不确定它是否可以从实体服务中获取数据并将其放入序列化缓存中。
所以:
您能为我建议一些框架或库来完成这项工作吗?还是您认为根据我的需求,我应该自己实现呢?
3个回答

7
我曾经在类似的N-Tier偶尔连接客户端中使用过Microsoft Sync Framework,效果很好。它自我更新以来已经有所改进,但我认为它仍然符合您的要求。 WCF 通过WCF运行良好,这就是我们使用的方式。(如何配置N-Tier同步应具备增量同步功能 同步服务非常擅长此项任务,但您可能需要将时间戳添加到同步表中。您的客户端数据库(在我的情况下是SQL Server CE数据库)保存了上次同步时使用的最后时间戳,然后在下一次同步期间使用该时间戳获取之后发生更改的所有内容。 可以将更改推送到服务器 同样,我们也这么做了。有许多钩子可提供自定义逻辑以验证数据。 离线访问/存储信息

在完全断开的情况下正常工作(前提是用户已经同步了他们的数据)。请参见离线场景

完全重新同步的可能性(损坏的缓存或新计算机)

客户端数据库保存所有同步信息(如果您想要,可以将知识放到服务器上,了解客户端已同步的内容)。如果删除本地数据库,则客户端将进行完全同步。

服务器端的数据提供程序是Entity Framework

这不是我使用它的方式,但同步提供程序是完全可定制的。我们曾经考虑过使用NHibernate,但请问为什么要这样做。开箱即用的Sync Services将允许您使用存储过程或直接表查询推送和拉取数据。这非常容易设置,并且由于您可能正在使用大量数据,因此运行非常快速,并且数据很容易在WCF边界上进行同步(尽管我们从xml格式化程序切换到二进制格式化程序以获得更好的性能)。

我们发现的是,尽管我们在服务器上使用了实体,但这些实体在客户端上并不一定有意义,因此我们在客户端上有了一整套新的实体。这也意味着我们在存储过程中剥离了客户端不需要的数据。同样,这非常容易,您无需涉及 ADO.net。然后,一旦数据在客户端上,我们使用 NHibernate 来读写本地数据库。 为 Microsoft Sync Framework 构建自定义同步提供程序 我需要重用当前的自定义身份验证 如果您指的是 WCF 自定义身份验证,则是的,因为我们有自己的 WCF 自定义安全令牌,而且没有任何影响。 额外奖励:某些类型具有特殊的同步(例如,我有一个包含小文件的数据库,但在客户端上,文件必须直接放在文件夹中) 简短的答案是我不知道,因为新框架中有一个文件同步提供程序,我没有使用过,但您还有两个选项。
  1. 在客户端同步期间,您可以实际上进入数据将被放入表中的点,并有机会将二进制数据提取出来并将其写入文件系统而不是数据库。
  2. 从同步中排除文件二进制数据,然后使用另一个进程在同步之后拉取此数据。由于我们正在拉取的软件包相当大,因此我们使用初始同步来拉取“元数据”,然后我们使用称为BITS的东西(它是Windows的一部分)异步地拉取文件。

Microsoft Sync Framework文件同步提供程序介绍

[更新]

回答评论中提出的问题。

  1. My application should works for different users on the same computer. In my case, I was using the isolated storage to guarantee that they works in a different location, is this possible with SQL Server CE?

    Our application was deployed via ClickOnce which would provide a separate installation of the application for each user but I don't think that is what is being asked. SQL CE is just an in memory database, you point the SqlCeEngine at the database file you want to load so isolated storage is perfect.

  2. As far as I know, SQL Server CE is like SQLite, how do you manage the schema creation?

    You can let Snyc Services create the database schema for you if you want and that will be good enough to get you going but in the long run you are probably going to have to change the schema at some point. This will probably be when you do an upgrade so you are better of thinking about it early on. I dealt with this by not thinking of the database as belonging to sync services but as something sync services is told it can use.

    When our application started up it did some house keeping like creating the database if it didn't exist or running database scripts if the application had just been upgraded.

  3. Do you know if there is somewhere an example of class implementation for this N-tier sync? I need to saw what interfaces I've to implement.

    The current stable release is 2.1 and I was using it just as 2.0 came out so all my work was in 1.0. Here is a link to the Microsoft Sync Framework 2.1 api on MSDN. I had to use the 1.0 docs to find the examples that I used to drive out our WCF interface so I don't know how far things have changed but you can use this to start with which defines the interface as this:

    [ServiceContract] public interface IServiceForSync { [OperationContract()] SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession);

    [OperationContract()]
    SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession);
    
    [OperationContract()]
    SyncSchema GetSchema(Collection<string> tableNames, SyncSession syncSession);
    
    [OperationContract()]
    SyncServerInfo GetServerInfo(SyncSession syncSession);
    

    }

  4. I suppose it's one service per data type?

不,正如您从上面看到的,只有一个服务。同步的内容取决于您在服务器上公开的内容以及客户端想要参与的内容。例如,我们有两个客户端,其中一个仅对数据的一小部分感兴趣,并且仅参与同步几个表格(称为SyncTable),而另一个则同步所有表格。

还有一个SyncGroup的概念,它们由应该作为一个事务持久化的相关更改组成,因为它们都是相关的,即如果其中一个失败,则全部失败。您还可以单独同步组,而无需同步所有内容。

  1. 我可以仅同步与用户相关的数据吗?
当您进行同步时,需要传递一个SyncParameter,其中包含可用于过滤返回给客户端的数据的值。如何:筛选行和列

你的提议似乎非常有趣,我有几个问题:1. 我的应用程序应该在同一台计算机上为不同的用户工作。在我的情况下,我使用隔离存储来保证它们在不同的位置工作,SQL CE 是否可以实现这一点?2. 据我所知,SQL CE 类似于 SQLite,您如何管理模式创建?3. 您是否知道是否有某个类实现的示例可供此 N 层同步使用?我需要了解要实现哪些接口。4. 我想这是每种数据类型一个服务吧?5. 我能只同步与用户相关的数据吗? - J4N
@J4N 我已经更新了答案以解决你提出的额外问题。 - Bronumski
我正在尝试实现您的解决方案,我有一个问题:您是如何处理删除操作的?如果删除了一个元素,客户端调用GetChanges操作时,您是如何知道的?您是将所有数据保留在数据库中并将其标记为已删除吗?还是您有一个包含所有已删除元素ID的表格? - J4N
@J4N 很抱歉,我已经换了工作,所以无法告诉你确切的情况。如果我没记错,我们管理过一个墓碑表(在 SQL Server 2008 之前,可能会使用更改跟踪为您完成此操作)。这可以让您处理硬删除。如果您正在执行软删除,则可能更容易。我认为这不是一项“一刀切”的解决方案。 - Bronumski

0

我已经考虑过了。但是用户只能访问数据库的部分副本(而且我需要客户端上的所有内容都通过一个安装程序安装)。 - J4N
安装SQL Express可以通过将其作为应用程序安装的先决条件来完成。据我所知,您可以指定过滤器以确定将推送哪些数据。 - Emond
嗯,这开始变得有趣了。您是说SQL Express的安装和配置可以在安装程序中完成?至于过滤器,我有些疑惑,我是否可以根据当前用户设置它们。 - J4N
好的,但这意味着我应该为每个用户拥有一个Windows用户/SQL用户吗?我只有一个SQL用户连接到数据库(而且这个用户名/密码只存储在服务器上)。 - J4N
如果可能的话,我会使用集成安全性。复制可以在不同的帐户上运行。 - Emond


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接