了解 CoreData 中 Transformables 的故障
Understanding the faulting of Transformables in CoreData
我的应用程序有问题,从我的数据库中删除大量数据需要很长时间。所以我开始调试并发现问题出在值转换器上!
为了查看问题,我创建了一个项目来隔离问题...
我有以下内容:
+-----------+ +-----------+
| Entity A | | Entity B |
+-----------+ +-----------+
| | | property |
| b | 1:1 | a |
+-----------+ +-----------+
所以 Entity A
与 Entity 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。
或者当然,也许可以优化您的值转换器以减少问题?
希望这对您有所帮助。祝你好运!
我的应用程序有问题,从我的数据库中删除大量数据需要很长时间。所以我开始调试并发现问题出在值转换器上!
为了查看问题,我创建了一个项目来隔离问题...
我有以下内容:
+-----------+ +-----------+
| Entity A | | Entity B |
+-----------+ +-----------+
| | | property |
| b | 1:1 | a |
+-----------+ +-----------+
所以 Entity A
与 Entity 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。
或者当然,也许可以优化您的值转换器以减少问题?
希望这对您有所帮助。祝你好运!