记录和管理冲突
在同步期间,同步应用程序可能会指示冲突必须保存在冲突日志中,而非立即解决。通过使用冲突日志,可以在非同步时间解决冲突,这样,就可以尽可能高效率地完成同步。
通过日志记录解决冲突
若要指示要保存并发冲突,应用程序将设置 SaveConflict(对于托管代码)或 SRA_TRANSFER_AND_DEFER(对于非托管代码)的冲突解决操作。若要指示要保存约束冲突,应用程序将设置 SaveConflict(对于托管代码)或 SCRA_TRANSFER_AND_DEFER(对于非托管代码)的冲突解决操作。
记录冲突
若要记录并发冲突,变更应用方调用 SaveConflict(对于托管代码)或 ISynchronousNotifyingChangeApplierTarget::SaveConflict(对于非托管代码)。在此方法中,提供程序保存冲突变更的元数据、冲突变更的日期以及指定的冲突知识。
若要记录约束冲突,变更应用方调用 SaveConstraintConflict(对于托管代码)或 ISynchronousNotifyingChangeApplierTarget2::SaveConstraintConflict(对于非托管代码)。在此方法中,提供程序保存冲突变更的元数据、冲突变更的日期、目标副本中冲突项的 ID、冲突原因以及指定的冲突知识。
在某一冲突存储于冲突日志中之前,提供程序必须确保该冲突不会被已处于冲突日志中的其他变更取代。为此,可以通过使用 Combine 方法(对于托管代码)或 ISyncKnowledge::Union 方法(对于非托管代码)创建日志知识,以便将所有冲突的冲突知识都合并到日志中。如果新冲突包含在日志知识中,它就是过时的并且不应添加到日志中。此日志知识可以按需创建,或者与冲突日志一起存储。如果存储该日志知识,则必须在添加冲突时通过使用 Combine(对于托管代码)或 Union(对于非托管代码)更新它。同样,在删除某一冲突时,必须通过使用Complement(对于托管代码)或 ISyncKnowledge2::Complement(对于非托管代码)更新日志知识。
删除过时的冲突
为了防止冲突日志增长得过大,必须从冲突日志中删除过时的冲突。
通过使用 Sync Framework 的变更应用方组件,最易于实现过时的冲突的检测和删除。为了将某一冲突连接到变更应用方,提供程序或冲突日志实现 IConflictLogAccess 和 IConflictLogWriter 接口(对于托管代码)或 IConflictLogAccess 和 IConflictLogWriter 接口(对于非托管代码)。冲突日志将传递给变更应用方,方法是使用
ApplyChanges 方法(对于托管代码)或 ISynchronousNotifyingChangeApplier2::ApplyChanges 方法(对于非托管代码)。在将冲突日志传递到变更应用方时,该变更应用方将在每个变更批结束时检测并删除日志中的过时的冲突。
对于未连接到某一变更应用方的冲突日志,该冲突日志必须自己管理过时的冲突。在将某一冲突添加到冲突日志中(取代日志中的冲突)时,该冲突可能会变得过时。发现这种情况的方法之一是根据新冲突的冲突知识测试日志中各冲突的变更版本。在某一冲突的变更版本包含在新冲突的冲突知识中时,现有的冲突将过时并且必须从日志中删除。在将某一变更(它取代日志中的冲突)应用于副本时,该冲突也可能会变得过时。发现这种情况的方法之一是在应用每一变更批后根据副本的知识测试日志中各冲突的变更版本。过时冲突的检测和解决可以作为同步会话的一部分执行,或者在其他时间执行。
解决日志中的冲突
冲突日志中的冲突可以作为同步会话的一部分解决,或者在其他时间解决。但是,冲突日志中的冲突不应在变更应用的过程中解决,否则可能会产生意外结果。
在日志中的冲突应用于副本时,它必须作为本地变更处置。为了解决冲突日志中的冲突,应用程序或提供程序将执行以下步骤:
增加副本的滴答计数。
更新项的变更版本或变更单位,以便通过更新的滴答计数反映本地副本所进行的变更。
通过使用 Combine(对于托管代码)或 Union(对于非托管代码)将副本的知识与冲突的知识结合起来,并且将合并后的知识作为副本的新知识保存。
将变更数据应用于副本。
从冲突日志中删除冲突。
内存中冲突日志
在提供程序报告约束冲突时,需要冲突日志。为了帮助提供程序报告不包含冲突日志的副本的约束冲突,Sync Framework 提供在内存中操作的冲突日志接口实现并且用于存储可能因约束冲突处理导致的临时冲突。此实现是 MemoryConflictLog 类(对于托管代码)或 IMemoryConflictLog 接口,可通过调用 IProviderSyncServices2::CreateMemoryConflictLog(对于非托管代码)获取该接口。
该内存中冲突日志实现还可以与永久的冲突日志一起使用。内存中冲突日志可用于提高性能,这是通过使用它来提供整个冲突日志的内存中缓存和处理临时冲突实现的。在某一永久冲突日志与内存中冲突日志链接在一起时,可以在同步完成后通过调用 Persist(对于托管代码)或 IMemoryConflictLog::Persist(对于非托管代码)将冲突保存到永久冲突日志中。