CoreData 不会删除自动生成的关系表中的记录

Posted

技术标签:

【中文标题】CoreData 不会删除自动生成的关系表中的记录【英文标题】:CoreData doesn't delete records in autogenerated relationship table 【发布时间】:2015-02-10 21:43:56 【问题描述】:

CoreData / SQLite 问题在这里...

如果你在 XCode 中创建两个实体 TableATableB,并在它们之间创建多对多关系,CoreData 将在运行时创建第三个 sqlite 表调用“Z_TableAToTableB”来管理两者之间的关系。

但是,我注意到当我删除 TableA 和 TableB 中的所有行时,Z_TableAToTableB 中的记录会保留一段时间。它们不会立即被删除。

这是设计使然吗?这真的很令人沮丧,并导致我的应用程序出现并发问题。我还在 TableA 和 TableB 之间设置了级联删除,因此从一个删除行将删除另一个行,但永远不会删除第三个表中的行。

如何删除ZTableAToTableB中的记录?

更新:

这是我的桌子的设置方式。为了便于讨论,让我们只关注 Project-Segment 关系。注意两个表之间的多对多关系。有时,我需要从 Project 表中删除 ALL 记录 并用一些新数据刷新它。但是当我这样做时,项目表的 PK 再次从 1 开始。 (当用户从​​我的应用程序的旧版本升级到我的应用程序的新版本时尤其如此,但我离题了)这对我来说很好,如果 Z_ProjectToSegment 中的关系记录得到删除,但他们没有。这会导致项目段之间的错误关系。

【问题讨论】:

你能显示删除代码吗?删除每个对象并保存托管对象上下文后,应删除实体之间的关系。此外,对象图是否在开发过程中变得不同步,从而留下了一些孤立的记录? 【参考方案1】:

我的猜测是您的删除规则错误,但您提到设置为级联。在内部,Core Data 可能会将旧的连接表四舍五入并在以后批量删除它们,它可能永远不会删除它们......谁知道呢。

最终,这不是我们应该担心的事情,即使我们这样做了,我们也无能为力(您真的,真的不想在 Core Data sqlite 文件中扎根并进行更改未经其许可)。

至于它“导致您的应用程序出现并发问题”,我发现这极不可能,我们需要一个更具体的例子。

【讨论】:

我的应用要求用户定期与我们的服务器“同步”他们的数据,以支持离线使用。我使用以下算法执行此操作: 1)删除表 A 和表 B 中的所有记录 2)提交 3)下载新数据 4)将新数据插入表 A 和表 B,并创建行之间的关系 我的并发问题应用程序的出现是因为,如果我删除 TableA 中的所有记录,并将更改提交到 NSManagedObjectContext,则 TableA 的主键从 1 开始。如果 Z_TableAToTableB 仍然包含 TableA id=1 和 TableB id 之间的关系,则会导致错误的关系=N. 我发现如果我删除第 2 步 [managedObjectContext save:nil],并在插入所有“新”记录后将其保存到最后,则表 A 的 PK 不会重新开始1. 但我发现这是一个愚蠢的解决方法。我应该可以随时调用 [managedObjectContext save:nil] 而不会产生这种影响。 有人建议,在删除之前,我通过遍历每个项目上的 ProjectToSegment 数组来打破两个表之间的关系,在每个项目上调用 removeObject: then删除实体。我会试试这个并报告我的发现。 听起来您的同步策略依赖于您能够基本上将整个对象图加载到内存中,同时删除它们,然后重新导入几乎总是完全相同的内容来自服务器的数据。如果这是准确的并且您的唯一目标是离线支持,那么这是实现这一目标的一种非常迂回的方式,我建议您多阅读同步理论。查找或创建是良好同步策略的一部分;销毁然后重新创建不是。 你说得对。不幸的是,我从最初编写它的承包商那里继承了这个(阅读:一起拍打),而且我没有足够的时间来偿还技术债务并完全重构同步算法(阅读:特性、特性、特性!)。我只是在尝试使用我得到的东西。【参考方案2】:

我已经设法解决了这个问题,方法是等到我的同步操作结束以保存 MOC..

同步算法是:

1) 删除所有记录(后台线程) 2) 保存后台 MOC 并与 UI 线程 MOC 合并。 3) 下载并插入新记录(后台线程) 4) 保存后台 MOC 并与 UI 线程 MOC 合并。

现在算法是……

1) 删除所有记录(后台线程) 2) 下载并插入新记录(后台线程) 3) 保存后台 MOC 并与 UI 线程 MOC 合并。

通过等到最后“保存” MOC,表永远不会真正为空,因此我成功地阻止了 CoreData 将 id PK 重置为 1。

我仍然担心没有办法指示CoreData“清理”关系表。它似乎随时可以清理它。但目前这个解决方案对我们有用,直到我们找到更好的同步算法。

【讨论】:

【参考方案3】:

我发现如果我有两个对象之间的许多关系 Ordered,则表永远不会被清理。如果我设置为未排序,则在删除两个对象后,表也会被清理。

在我看来,有序关系在清理订单表时存在一些问题。

【讨论】:

你能解释更多吗?正如您在我的屏幕截图中看到的,两个表都没有设置为有序。当我删除两个表的内容时,在运行时创建的第三个表没有(立即)清理。它最终会被清理干净,但发生这种情况时似乎无法预测。

以上是关于CoreData 不会删除自动生成的关系表中的记录的主要内容,如果未能解决你的问题,请参考以下文章

根据关系表从父表中获取记录 - CoreData

如何在有外键关系的表中删除数据

iphone coredata 删除通过关系连接的两个实体之间的记录

iOS 核心数据关联

如何计入coredata(聚合)?

CoreData 中的删除不会删除;重新启动后出现已删除的对象