了解 CoreData 中 Transformables 的故障

Understanding the faulting of Transformables in CoreData

我的应用程序有问题,从我的数据库中删除大量数据需要很长时间。所以我开始调试并发现问题出在值转换器上!

为了查看问题,我创建了一个项目来隔离问题...

我有以下内容:

+-----------+     +-----------+
| Entity  A |     | Entity  B |
+-----------+     +-----------+
|           |     | property  |
| b         | 1:1 | a         |
+-----------+     +-----------+

所以 Entity AEntity B 有 1:1 关系。 Entitiy B 有一个名为 property 的 属性,它是 Transformable 并且有一个 ValueTransformer。 A对B的删除规则为nullify.

现在我创建了 A 和 B 的一个实例,link 它们并向 属性 中写入一些内容。保存上下文,一切都按预期工作。

现在我想删除 Entity A 的所有对象。我创建一个获取请求,并删除所有实体。在我的示例中,我是这样做的:

context.perform {
    let fetchRequest = NSFetchRequest<EntityA>(entityName: "EntityA")
    guard let allEntities = try? context.fetch(fetchRequest) else { return }

    for entity in allEntities {
        context.delete(entity)
    }
    try? context.save()
}

现在,当保存发生时,将调用值转换器 reverseTransformedValue。我不明白为什么?!?因为我不访问那个 属性...我没有设置或得到它...

如果有人能为我提供一些启发,那就太好了。

我在这里也有我的示例项目:https://www.dropbox.com/s/651dmyughosr90p/ValueTransformerIssue-Sample.zip?dl=0

这是一个有趣且有点令人惊讶的结果,但我认为这是 Core Data 正常运行的结果。关于 Core Data 的一些背景细节:

  • 读取对象时,通常是"fault"。 属性 除非您将获取请求配置为需要加载,否则不会立即加载值。
  • 当故障对象"fires",所有 属性值被加载。当您访问任何 属性 值时,这会自动发生,因此如果您查找一个 属性,所有 属性 值都会被加载。
  • 为了更改 属性 上的值,Core Data 将加载 属性 值。

在你的情况下,似乎正在发生的事情是:

  • 您获取 EntityA 的实例。
  • 您删除那些实例。
  • 由于您使用 "nullify" 作为删除规则,删除 EntityA 意味着 Core Data 需要通过将其值设置为 [=13= 来修改相应的 EntityB ] 为零。
  • 内部 Core Data 需要加载 EntityB 实例。由于它正在修改其中一个属性,因此它首先加载所有属性。在这一点上,你的价值转换器执行,即使它在这里并不真正需要。

如果您的价值转换器正在损害性能,您可能会尝试解决一些问题,包括:

  • 将此 属性 移至与 EntityB 相关的单独实体。 属性 故障时不会触发关系故障,因此无效规则不会加载此新实体的实例。
  • 虽然 NSBatchDeleteRequest 不会遵守删除规则(因此 "nullify" 不会应用),但您可以将其中一个与 NSBatchUpdateRequest 结合使用以修复关系。例如,对 EntityA 个实例进行批量删除,然后进行批量更新,以将受影响的 EntityB 个实例的关系设置为 nil。

或者当然,也许可以优化您的值转换器以减少问题?

希望这对您有所帮助。祝你好运!