
(可以在下面的问题中跳过这个冗长的描述)
我分析了Core Data的sqlite增量存储如何通过检查它生成的sql日志来解决这个问题,并得出以下结论:
>数据库中的每个实体表都有一个Z_OPT列,它指示从1(初始插入)开始修改此实体(行)的特定实例的次数.@H_403_14@>每次修改托管对象时,其对应数据库行中的Z_OPT值都会递增.@H_403_14@>存储维护NSIncrementalStoreNode实例的缓存(在Core Data docs中称为行缓存),每个实例的版本属性等于由托管对象的行上的先前SELECT或UPDATE SQL查询返回的Z_OPT值.@H_403_14@>当从NSManagedobjectContext返回托管对象时(例如,通过对其执行NSFetchRequest),MOC会创建包含此版本号的此对象的快照.@H_403_14@>修改或删除对象时,Core Data通过比较缓存的行和对象快照的版本,确保未在上下文之外修改或删除它.当-save:在对象所属的上下文上调用时,所有这些都会发生.如果版本不同,则基于集合并策略检测并处理合并冲突.
保存MOC时,为每个修改/删除的对象调用-newValuesForObjectWithID:withContext:error:方法,后者又返回带有版本号的NSIncrementalStoreNode.然后将此版本与快照的版本进行比较,如果它们不同,则保存将因适当的合并冲突而失败(至少使用默认合并策略).
这个简单的用例适用于我的商店,因为-newValuesForObjectWithID:withContext:error:首先检查行缓存,如果在其他上下文中使用相同的商店实例同时修改了该对象,那么这就足够了.如果是这种情况,则缓存包含具有更高版本号的更新行,该行足以检测冲突.
但是,我如何检测到底层数据库已经在我的商店外被修改,可能是由使用相同数据库文件的其他应用程序或其他商店实例?我知道这是一个不常见的边缘情况,但Core Data正确处理它,我宁愿做同样的事情.
Core Data的商店使用这些SQL查询来更新/删除对象的行:
UPDATE ZFOO SET Z_OPT=Y,(...) WHERE (...) AND Z_OPT=XDELETE FROM ZFOO WHERE (...) AND Z_OPT=X
哪里:@H_403_14@X – 商店最后知道的版本号(来自缓存)@H_403_14@是 – 新版本号
如果此类查询失败(没有行受影响),则会在商店的缓存中更新该行,并将其版本与先前缓存的版本进行比较.
我的问题是:自定义NSIncrementalStore如何通知Core Data一些更新/删除/锁定的对象发生了乐观锁定失败?只有商店能够告诉它在处理传递给它的NSSaveChangesRequest时它的-executeRequest:withContext:error:方法.
如果底层数据库在存储下没有更改,则检测到冲突,因为Core Data在商店上执行保存更改请求之前,在每个已修改/已删除/已锁定的对象上调用-newValuesForObjectWithID:withContext:error:.我无法找到NSIncrementalStore的任何方法来通知Core Data在开始处理保存请求后发生了乐观锁定失败.是否有一些无证的方法可以做到这一点?核心数据似乎在这种情况下抛出一些异常,然后神奇地转换为失败的保存请求,NSError列出了所有冲突.我只能通过从-executeRequest返回nil来模仿这一点:withContext:error:并由我自己创建错误消息.我认为在这种情况下必须有一种方法来使用标准的Core Data冲突处理机制.
解决方法 我意识到这不是你问题的答案,但我会尝试给你我对CoreData的观点以及与数据库的关联:(一级缓存)@H_403_14@NSPesistentStoreCoordinator NSPersistentStore ==与数据库的单个连接
(二级缓存)@H_403_14@NSManagedobjectContext ==缓存保持更改的连接
因此,根据我的理解,您的问题是您与商店有多个连接,每个连接都进行了更改,但您对记录没有中央版本控制权.@H_403_14@您的商店将收到-executeRequest:withContext:error:with NSSaveRequestType@H_403_14@然后,您将负责验证记录版本是否匹配,如果在连接级别(级别1)中发现冲突,则报告上下文(级别2)与协调器之间的版本不匹配.@H_403_14@您需要在连接(级别1)和商店之间报告版本不匹配.@H_403_14@为了能够执行此 *** 作,您的商店必须在其所有连接(ConnectionManager)上报告对其的更改,或者它可能提供对其执行的更改的挂钩.@H_403_14@我不是sqlite专家,但sqlite API在该领域确实提供了一些东西:@H_403_14@update hook@H_403_14@commit hook@H_403_14@changes@H_403_14@total changes@H_403_14@(我没有设置这种钩子的经验,但如果CoreData使用它们,它将不会显示在调试日志中)
您可以通过设置错误指针(NSError **)并将其内部数据设置为与CoreData协调器正在设置的内容数据相匹配来报告这些错误(创建合并冲突并根据需要在其中设置信息)
请注意,乐观锁定失败只会在-executeRequest期间发生:withContext:error:@H_403_14@(除非你有一个与商店的流氓连接,一个没有经理跟踪的连接.@H_403_14@为了支持这种行为,您的经理可能需要验证每个记录,因为它已经提交了保存[巨大的性能成本],或者对最近对记录所做的更改使用了一些挂钩@H_403_14@)
要处理与商店的多个连接,您可能需要具有由商店URL键入的NSIncrementalStoreNode的共享缓存:@H_403_14@静态的 @{@H_403_14@url1:actualCacheMapPing1,@H_403_14@url2:actualCacheMapPing2,@H_403_14@…@H_403_14@}@H_403_14@保存到商店的每个连接将再次验证商店url实际缓存.
希望这对你有所帮助.
总结以上是内存溢出为你收集整理的ios – NSIncrementalStore子类中的乐观锁定支持全部内容,希望文章能够帮你解决ios – NSIncrementalStore子类中的乐观锁定支持所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)