CoreData:从捆绑的数据库中迁移数据

Posted

技术标签:

【中文标题】CoreData:从捆绑的数据库中迁移数据【英文标题】:CoreData:Migrate data from bundled db 【发布时间】:2015-11-13 13:39:27 【问题描述】:

我们的应用有一个基于单个 coredata 模型的 coredata 存储。有只读数据,也有读写数据。

只读数据已预加载并与应用程序捆绑在一起,因此在全新安装时,此数据库将复制到应用程序沙箱,并从那里通过 web 服务更新数据库(即只有更改的数据将从 Web 服务更新,从而减少传输的数据)。

现在我们需要向只读实体添加更多属性。

轻量级迁移将有助于轻松升级架构,但问题在于新数据,因为我们正在向所有只读实体添加新属性,所有数据记录都已更改,并且网络服务同步可能需要大量时间下载和更新数据。为避免这种情况,我们将更新的数据与应用程序捆绑在一起(这将解决全新安装的问题)。但是对于正在升级应用程序的用户,是否有一种标准机制可以从捆绑的数据库中复制只读实体并将这些实体更新到沙箱中的现有数据库,以便他们获得更新的只读数据以及他们的读取- 写入数据保持不变。

更新

这是场景,

我将 X.sqlite 与 proj 捆绑在一起(具有新架构),如果 X.sqlite 在 doc dir 中不存在,则我将其复制并从那里一切正常。现在在 App 更新场景中,X.sqilte 将已经存在于 doc dir 中并且不会被复制,并且迁移助手将迁移架构。所以现在我们有了 X.sqlite,它在 doc dir 中具有新模式,但旧数据(没有新属性)。现在我想知道是否有一种方法可以将捆绑的 X.sqlite 中的数据与 doc 目录中的数据合并。我想知道是否有合并的过程。

更准确地说

以下是实体

*存储 - 只读

*产品 - 只读

*ProductGroups - 只读

*ShopList - 基于用户

都在同一个型号和同一个商店。

现在商店/产品/产品组有额外的属性。

轻量级迁移器将迁移 X.Sqlite 的模式,以便 DB 将具有新的属性列。 现在我关心的是下一步,

我们以 Store 为例。 Store 有两个新属性 latitude 和 logitude。现在的问题是如何复制数据?步骤

将捆绑的数据库复制到具有差异名称的 doc 目录? 创建一个新的持久性协调器? 读取捆绑的数据并获取对象? 然后遍历现有的数据库?

【问题讨论】:

各位,我们将不胜感激 【参考方案1】:

如果我理解了您的问题:您想在应用更新期间更新只读数据,同时保留用户已更改的读写数据不变。

有几种方法可以实现这一点:

    有两个独立的数据库。一个数据库可以读写 数据和另一个只读数据。它们可以相互关联 使用获取的属性。在更新期间,更换或更新 只读数据库——同时保持读写数据库完好无损。 使用后台线程更新数据库。更新代码将 拥有自己的 ManagedObjectContext——但共享相同 持久存储。从同步主 ManagedObjectContext 使用某种协议的后台线程。

如果您选择从 Web 服务更新,则从后台线程更新的第二个选项可能会很有效。

如果我没有理解您的问题,请澄清。

【讨论】:

感谢您的回复,我将 X.sqlite 与 proj 捆绑在一起,如果 X.sqlite 在 doc dir 中不存在,我将其复制并从那里一切正常。现在在 App 更新场景中,X.sqilte 已经存在并且不会被复制,迁移助手将迁移架构。所以现在我们有了带有新模式但旧数据的 X.sqlite。现在我想知道是否有一种方法可以将捆绑的 X.sqlite 中的数据与 doc 目录中的数据合并。我想知道是否有合并的过程,我想了解更多关于您的第二种方法。【参考方案2】:

好吧,经过大量研究,我终于实现了我的目标,以下是我所做的路径和解决方案

溶胶 1

    将只读和读写数据放在不同的数据库中,这样如果有任何主数据更新,我可以安全地删除只读数据库,并且我可以保护用户的数据,但考虑到我拥有的时间表和约束,这对我来说是不可能的。在此处发帖,以便对其他人有所帮助。

溶胶 2

我想尝试将捆绑数据库中的新数据合并到现有数据库中,我想将现有数据库中的用户数据合并到新数据库中。以下是完成的步骤。 --> 创建了一个新的数据上下文。

--> 创建了一个新的持久协调器

--> 将捆绑的 db 重命名为 _v2 并将其复制到 Doc 目录中,现在我们在 doc 目录中有 2 个 DB 我拿了一些应用程序Importing large data sets

--> 现在使用 ManagedObject 克隆类别,我将所有用户信息数据从现有数据库复制到新数据库 _v2。在这里找到类别NSManagedObject+Clone

--> 工作正常,现在我的 _v2 数据库包含新的只读数据和旧数据库中的用户数据。

--> 现在我需要将控制权交还给默认数据上下文

--> 我试图将旧上下文的 PSC 更改为新的 PSC,但系统不允许我这样做。

--> 然后我尝试将旧上下文的持久性存储更改为新存储,但我收到错误消息说数据库已经存在。 (migratePersistentStore:toURL:options:withType:error:)

--> 我的想法在这里用完了。

溶胶 3

然后,我与其他一些同事讨论了我的问题,他们建议以不同的格式提供新数据,这很成功。正如我已经提到的,我的应用程序具有以 JSON 格式下载新数据并将其合并到核心数据的逻辑,为什么我可以提供一个包含新数据的 JSON 文件以及我的应用程序?

我从 web 服务收集了新的响应并创建了一个 JSON(不是很大,只有 1.5MB)并附加了应用程序包,对于更新应用程序的用户,我将读取 JSON 数据而不是核心数据合并在本地 并初始合并到核心数据数据库,数据库将有新的只读数据和完整的用户数据。初始合并后,一切都将通过在线同步处理。

【讨论】:

以上是关于CoreData:从捆绑的数据库中迁移数据的主要内容,如果未能解决你的问题,请参考以下文章

CoreData 迁移和数据映射:从现有属性创建新实体

从实体中删除属性后迁移 CoreData 时出错

从 sqlite3 迁移到 CoreData?

静态库中的 CoreData 自动迁移

iOS CoreData 版本升级和数据库迁移

iOS CoreData版本升级和数据库迁移