我应该忽略_SCoreData ConstraintViolationException 吗?

Posted

技术标签:

【中文标题】我应该忽略_SCoreData ConstraintViolationException 吗?【英文标题】:Should I ignore _NSCoreDataConstraintViolationException? 【发布时间】:2020-06-27 15:21:15 【问题描述】:

由于某种原因,我最近才发现 Core Data 的唯一约束。它看起来比替代方案更干净(先进行提取,然后在指定的上下文中插入缺失的实体),所以我决定重构所有现有的持久性代码。

如果我做对了,它的要点是始终插入一个新实体,并且只要我有适当的合并策略,保存上下文就会以更有效的方式处理唯一性。问题是每次我使用插入的实体保存上下文时,我都会得到一个NSCoreDataConstraintViolationException,但没有错误。当我进行提取以确保

    确实只有一个实例具有唯一字段 对该实体应用了其他更改

一切似乎都还好,但我仍然担心这个异常,因为我会保存,因此经常得到它,在某些情况下每秒几次。

我的项目是在 Objective-c 中,我知道那里的异常很昂贵,所以我怀疑我是否遗漏了什么。

Here是一个有这个问题的示例项目(就几行代码,一定要加异常断点)

【问题讨论】:

【参考方案1】:

NSMergeByPropertyObjectTrumpMergePolicy 和约束不是有用的工具,也不应该使用。管理唯一性的正确方法是在插入之前进行 fetch,因为它看起来您已经在做。

让我们从为什么唯一正确的合并策略是NSErrorMergePolicy 开始。您应该只在同步的情况下写入核心数据(performBackgroundTask 还不够need an operation queue)。如果您有两个 performBackgroundTask 同时运行并且它们相互矛盾,那么您将丢失数据。合并策略是回答“您希望丢失哪些数据?”的问题。正确答案是“不要丢失我的数据!”这是NSErrorMergePolicy

当你有一个约束时,同样的问题也会发生。假设您有一个对电话号码具有唯一约束的实体。然后您尝试插入另一个具有相同电话号码的实体。你想发生什么?这取决于数据到底是什么。可能是两个不同的人,电话号码应该不同(可能他们缺少区号),或者可能是一个人,数据应该合并。或者您可能对 uniqueID 有限制,并且该数字应该只是递增。但在数据库级别它不知道。它总是只是进行合并。它会默默地丢失数据。

您可以创建自定义NSMergePolicy 并检查NSConstraintConflict 以决定做什么。但在实践中,每次编辑数据库时都必须考虑每次更改意味着什么,这在将更改写入数据库的上下文之外可能非常困难。换句话说,约束和合并策略的问题在于,它运行在应用程序的错误级别上,无法有效地处理问题。

使用具有error 合并策略的约束是可以的,因为它是一种查找应用问题的方法(只要您监控崩溃并修复它们)。但是您仍然需要在插入之前进行 fetch 以确保不会发生错误。

如果您想清理代码,那么只需在一个地方创建您的对象。 objectWithId:createIfNeed:inContext: 之类的东西会进行获取和创建。

【讨论】:

虽然我同意,但我不会以这种方式概括它。这实际上取决于上下文,您如何使用它,如果您使用的是串行队列,......我的意思是 - 每个工具都可以以错误的方式和好的方式使用。了解该工具的功能以及应该注意的潜在问题始终至关重要。 使用合并策略和约束要求您在 全局 级别上了解可能会创建哪些冲突以及您希望如何解决这些冲突。这是一个更难的问题,然后知道对数据库进行一次编辑可能会产生什么冲突。合并策略的约束使问题变得更难而不是更容易。当然,您可以用更难的方式解决问题 - 但您为什么要这样做? 感谢您的回答和 cmets,但他们并没有完全回答我的问题。在这个阶段,我想知道,这些警告是否只是处理约束冲突的内部核心数据机制,最重要的是,它们是否会对性能产生任何影响。 使用仪器并测量它。这是唯一有效的答案。

以上是关于我应该忽略_SCoreData ConstraintViolationException 吗?的主要内容,如果未能解决你的问题,请参考以下文章

在使用Sphinx文档时,我应该告诉VCS忽略哪些文件? [关闭]

行中忽略的小部件对齐

为啥 Coverage.py 会忽略没有覆盖的文件?

clock constrain

如何为所有函数和类包含cpp文件但忽略main函数?

固定原子层脚本Atom_constrain.py介绍