我过去曾将 Microsoft Sync Framework 用于类似的 N-Tier 偶尔连接的客户端,并且效果很好。自从我上次使用它以来它一直在发展,但这是我看到它满足您的要求的方式。
WCF
在 WCF 上运行良好,这就是我们使用它的方式。(如何:配置 N 层同步)
应该有增量同步
同步服务可以很好地做到这一点,但您可能需要在同步表中添加时间戳。您的客户端数据库(在我的情况下是 SQL Server CE 数据库)保存上次同步时使用的最后一个时间戳,然后它将使用它来获取在下一次同步期间更改的所有内容。
可以将更改推送到服务器
我们又这样做了。有很多钩子可以在服务器上提供自定义逻辑来验证数据。
离线访问/存储信息
在完全断开连接的情况下工作正常(假设用户已经先同步了他们的数据)。请参阅离线场景。
可以进行完全重新同步(缓存损坏或新计算机)
它是保存所有同步信息的客户端数据库(如果需要,您可以将有关客户端已同步的内容的信息放到服务器上)。如果您删除本地数据库,则客户端将执行完全同步。
服务器端的数据提供者是 Entity Framework
这不是我使用它的方式,但同步提供程序是完全可定制的。我们本来打算做一个 NHibernate 的,但是问问自己为什么要这样做。开箱即用的同步服务将允许您使用存储过程或直接表查询来推送和拉取数据。这很容易设置,因为您可能使用大量数据,所以运行速度非常快,并且数据很容易跨 WCF 边界同步(尽管我们确实从 xml 格式化程序切换到二进制格式化程序以获得更好的性能)。
我们发现只是因为我们在服务器上使用了实体,它们在客户端上不一定有意义,因此我们在客户端上有了一组全新的实体。这也意味着我们在存储过程中剥离了客户端不需要的数据。同样,这很容易,您不需要弄脏 ADO.net。然后,一旦数据在客户端上,我们使用 NHibernate 读取和写入本地数据库。
为 Microsoft Sync Framework 构建自定义同步提供程序
我需要重用我当前的自定义身份验证
如果您的意思是 WCF 自定义身份验证,那么可以,因为我们有自己的 WCF 自定义安全令牌,它运行良好,没有任何影响。
奖励:某些类型有特殊的同步(例如,我有一个包含小文件的数据库,但在客户端,文件必须直接放在文件夹中)
简短的回答我不知道,因为他们是我没有使用过的新框架中的文件同步提供程序,但您还有另外两个选择。
在客户端同步期间,您实际上可以挂钩数据将被放入表中的点,您有机会提取二进制数据并将其写入文件系统而不是数据库。
从同步中排除文件二进制数据,并在同步后使用另一个进程拉下此数据。我们这样做是因为我们拉下的包非常大,所以我们使用初始同步来拉下“元数据”,然后我们使用称为BITS的东西,它是 Windows 的一部分来异步拉下文件。
Microsoft Sync Framework 文件同步提供程序简介
[更新]
回应评论中提出的问题。
我的应用程序应该适用于同一台计算机上的不同用户。在我的情况下,我使用隔离存储来保证它们在不同的位置工作,这对于 SQL Server CE 是否可行?
我们的应用程序是通过 ClickOnce 部署的,它将为每个用户提供单独的应用程序安装,但我认为这不是所要求的。SQL CE 只是一个内存数据库,您将指向SqlCeEngine
要加载的数据库文件,因此隔离存储是完美的。
据我所知,SQL Server CE 就像 SQLite,你如何管理模式创建?
如果需要,您可以让 Snyc Services 为您创建数据库架构,这足以让您继续前进,但从长远来看,您可能不得不在某个时候更改架构。这可能会在您进行升级时进行,因此您最好尽早考虑它。我通过不将数据库视为属于同步服务而是将其视为同步服务被告知它可以使用的方式来处理这个问题。
当我们的应用程序启动时,它会做一些内务处理,比如如果数据库不存在则创建数据库,或者如果应用程序刚刚升级,则运行数据库脚本。
你知道是否有这个 N 层同步的类实现示例吗?我需要看看我必须实现哪些接口。
当前的稳定版本是 2.1,我在 2.0 发布时使用它,所以我所有的工作都在 1.0 中。这是MSDN 上Microsoft Sync Framework 2.1 api 的链接。我必须使用 1.0 文档来查找我用来驱动 WCF 接口的示例,所以我不知道事情发生了多大的变化,但你可以使用它来开始,它将接口定义为:
[ServiceContract] 公共接口 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);
}
我想每种数据类型都有一项服务?
不,正如您从上面看到的,只有一项服务。同步的内容取决于您在服务器上公开的内容以及客户端想要参与的内容。例如,我们有两个客户端,一个只对一小部分数据感兴趣并且只参与同步几个表(称为a SyncTable
) 其他同步所有表的地方。
还有一个 a 的概念SyncGroup
,这些由相关的更改组成,这些更改应该以事务方式持久化,因为它们都是相关的,即如果一个失败,它们都会失败。您还可以单独同步组,而无需同步所有内容。
- 我可以只同步与用户相关的数据吗?
绝对地。当您进行同步时,您会传递一个SyncParameter
包含值的值,您可以使用这些值来过滤返回给客户端的数据。如何:过滤行和列。