【问题标题】:Good .Net Synchronization framework for n-tier architecture适用于 n 层架构的良好 .Net 同步框架
【发布时间】:2012-06-12 09:24:21
【问题描述】:

对于一个项目,我需要改变服务器和客户端之间的通信。

实际上它是一个托管在控制台应用程序中的 WCF 服务,它将整个表格内容发送到客户端,客户端将其所有本地缓存​​替换为新内容。

客户端应用程序可以离线工作(我们有一个区域缓存,它通过序列化在磁盘上持久化,我们还有一个事务列表,它存储了连接后我们必须发送到服务器的所有更改)。

问题是这种同步现在将发生在 GSM 连接上,发送整个表格内容真的很繁重。

所以要么我自己实现所有这些(设置修改日期,存储上次同步日期,只获取更新的字段,更新我的缓存),要么我可以找到一个标准的方法来做到这一点。我认为专门的库会做得更好,因为他们已经想到了很多我当然没有的场景。

同步层的耦合度很低,所以改变它的工作方式没什么大不了的。

我的项目要求是:

  • 应该有增量同步
  • 可以将更改推送到服务器
  • 离线访问/存储信息
  • 可以进行完全重新同步(缓存损坏或新计算机)
  • 服务器端的数据提供者是Entity Framework
  • 我需要重用当前的自定义身份验证
  • 奖励:某些类型有特殊的同步(例如,我有一个包含小文件的数据库,但在客户端,文件必须直接放在文件夹中)

我环顾四周看看存在什么。

我发现了一些关于 Microsoft Sync Framework 的东西,但它似乎非常面向 ADO.Net,我不确定它是否可以从实体服务中获取数据并将它们放入序列化缓存中。

所以:

你能给我一些框架或库来完成这项工作吗?还是您认为考虑到我的需求,我应该自己实现这个?

【问题讨论】:

    标签: .net wcf entity-framework synchronization n-tier-architecture


    【解决方案1】:

    我过去曾将 Microsoft Sync Framework 用于类似的 N-Tier 偶尔连接的客户端,并且效果很好。自从我上次使用它以来,它一直在发展,但我认为它满足了您的要求。

    WCF

    在 WCF 上运行良好,这就是我们使用它的方式。 (How to: Configure N-Tier Synchronization)

    应该有增量同步

    同步服务可以很好地做到这一点,但您可能需要在同步表中添加时间戳。您的客户端数据库(在我的例子中是 SQL Server CE 数据库)保存上次同步时使用的最后一个时间戳,然后它将使用它来获取在下一次同步期间更改的所有内容。

    可以将更改推送到服务器

    我们又这样做了。有很多钩子可以在服务器上提供自定义逻辑来验证数据。

    离线访问/存储信息

    在完全断开连接的情况下可以正常工作(前提是用户已经先同步了他们的数据)。见Offline Scenarios

    可以进行完全重新同步(缓存损坏或新计算机)

    保存所有同步信息的是客户端数据库(如果您愿意,您可以将有关客户端已同步的内容的信息放到服务器上)。如果您删除本地数据库,则客户端将执行完全同步。

    服务端的数据提供者是Entity Framework

    这不是我使用它的方式,但同步提供程序是完全可定制的。我们本来打算做一个 NHibernate 的,但是问问自己为什么要这样做。开箱即用的同步服务将允许您使用存储过程或直接表查询来推送和拉取数据。这很容易设置,因为您可能使用大量数据,所以运行速度非常快,并且数据很容易跨 WCF 边界同步(尽管我们确实从 xml 格式化程序切换到二进制格式化程序以获得更好的性能)。

    我们发现只是因为我们在服务器上使用了实体,它们在客户端上不一定有意义,因此我们在客户端上有了一组全新的实体。这也意味着我们在存储过程中剥离了客户端不需要的数据。同样,这很容易,您不需要弄脏 ADO.net。然后,一旦数据在客户端上,我们使用 NHibernate 读取和写入本地数据库。

    Building Custom Sync Providers for the Microsoft Sync Framework

    我需要重复使用当前的自定义身份验证

    如果您的意思是 WCF 自定义身份验证,那么可以,因为我们有自己的 WCF 自定义安全令牌,它运行良好,没有任何影响。

    奖励:某些类型有特殊的同步(例如,我有一个包含小文件的数据库,但在客户端,文件必须直接放在文件夹中)

    简短的回答我不知道,因为他们是新框架中的文件同步提供程序,我没有使用过,但您还有其他两个选择。

    1. 在客户端同步期间,您实际上可以挂钩到数据将被放入表中的位置,您有机会提取二进制数据并将其写入文件系统而不是数据库。

    2. 从同步中排除文件二进制数据,并在同步后使用另一个进程拉取此数据。我们这样做是因为我们拉下的包非常大,所以我们使用初始同步来拉下“元数据”,然后我们使用称为 BITS 的东西,它是 Windows 的一部分来异步拉下文件。

    Introduction to Microsoft Sync Framework File Synchronization Provider

    [更新]

    针对cmets提出的问题。

    1. 我的应用程序应该适用于同一台计算机上的不同用户。就我而言,我使用隔离存储来保证它们可以在不同的位置工作,这可以通过 SQL Server CE 实现吗?

      我们的应用程序是通过 ClickOnce 部署的,它将为每个用户提供单独的应用程序安装,但我认为这不是所要求的。 SQL CE 只是一个内存数据库,您将SqlCeEngine 指向您要加载的数据库文件,这样隔离存储就完美了。

    2. 据我所知,SQL Server CE 就像 SQLite,你如何管理架构创建?

      如果需要,您可以让 Snyc Services 为您创建数据库架构,这足以让您继续前进,但从长远来看,您可能不得不在某个时候更改架构。这可能会在您进行升级时进行,因此您最好尽早考虑它。我通过不将数据库视为属于同步服务而是将其视为同步服务被告知它可以使用的方式来处理这个问题。

      当我们的应用程序启动时,它会做一些内务处理,例如在数据库不存在时创建数据库,或者在应用程序刚刚升级时运行数据库脚本。

    3. 你知道是否有这个 N 层同步的类实现示例吗?我需要看看我必须实现哪些接口。

      当前的稳定版本是 2.1,我在 2.0 发布时使用它,所以我所有的工作都在 1.0 中。这是 MSDN 上Microsoft Sync Framework 2.1 api 的链接。我必须使用 1.0 文档来查找用于驱动 WCF 接口的示例,所以我不知道事情发生了多大变化,但您可以使用 this 开始,它将接口定义为:

      [服务合同] 公共接口 IServiceForSync { [操作合同()] 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. 我想每种数据类型只有一个服务?

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

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

    1. 我可以只同步与用户相关的数据吗?

    当然。当您进行同步时,您会传递一个SyncParameter,其中包含可用于过滤返回给客户端的数据的值。 How to: Filter Rows and Columns.

    【讨论】:

    • 您的提议似乎很有趣,我有几个问题: 1. 我的应用程序应该适用于同一台计算机上的不同用户。就我而言,我使用隔离存储来保证它们在不同的位置工作,这对 SQL CE 可行吗? 2. 据了解,SQL CE 和 SQLite 一样,如何管理模式创建? 3. 你知道在某个地方是否有这个 N 层同步的类实现示例吗?我需要看看我必须实现哪些接口。 4. 我想每种数据类型都有一项服务? 5. 我可以只同步与用户相关的数据吗?
    • @J4N 我已更新答案以解决您提出的其他问题。
    • 我正在尝试实施您的解决方案,我有一个问题:您如何管理删除?如果一个元素被删除了,你怎么知道客户端调用 GetChanges 操作的时候?您是否将所有数据都保存在数据库中并将它们标记为已删除?或者您有一个包含已删除元素的所有 Id 的表?
    • @J4N 不幸的是我换了工作,所以我不能准确地告诉你。如果我没记错的话,我们管理了一个墓碑表(pre sql server 2008,它可以通过更改跟踪为您执行此操作)。这允许您处理硬删除。如果您正在进行软删除,那么它可能更容易。我不认为它是一刀切的。
    【解决方案2】:
    【解决方案3】:

    取决于您可以或愿意部署和公开您可以使用的服务器的方式SQL Server Replication

    复制可以处理所有繁琐的replication tasks,而您则担心应用程序。

    您可以考虑安装 SQL Express 并使用合并复制。

    编辑 Using parameterized filters 管理将复制哪些数据,installing SQL Express as a prerequisite using a bootstrapper。显然微软没有为 SQL Express here is a discussion on a that提供引导程序

    【讨论】:

    • 我已经考虑过了。但用户只能访问数据库的部分副本(我需要客户端上的所有内容都通过 ONE setup 安装)
    • 安装 SQL Express 可以通过将其添加为应用程序安装的先决条件来完成。据我所知,您可以指定过滤器来确定将推送哪些数据。
    • 哼,开始有意思了。所以你说我SQL Express的安装和配置可以在setup里面完成吗?对于过滤器,我有一些疑问,我可以根据当前用户设置它们。
    • 好的,但这意味着我应该为每个用户都有一个 windows 用户/sql 用户?我只有一个 SQL 用户可以连接到数据库(并且这个用户/密码只存储在服务器上)。
    • 如果可能的话,我会使用集成安全性。复制可以在不同的帐户上运行。
    猜你喜欢
    • 1970-01-01
    • 2012-03-04
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 2017-07-16
    相关资源
    最近更新 更多