【问题标题】:CoreData migration of database to new codebaseCoreData 将数据库迁移到新代码库
【发布时间】:2020-12-07 03:47:26
【问题描述】:

我正在对应用进行大规模更新。通过大更新读取完整的返工 - 全新的代码库从头开始但具有相同的 bundleID 能够在发布时放弃旧应用程序。

我目前正在研究 CoreData 迁移,但遇到了一些问题:

  • 旧应用只有一个数据库:OldData
  • 新应用将有多个数据库,但只有一个我们感兴趣:NewData

我想从OldData加载信息,手动迁移到NewData,然后删除OldData中的数据。

我们已将OldData 的一个版本复制到新应用中,但是当我们搜索保存的对象时,没有返回任何内容。

我们返回数据库:

let coreDataManager = CoreDataManager(modelName: "OldData")
let context = coreDataManager.persistentContainer.viewContext

if try context.count(for: NSFetchRequest(entityName: "OldObjectName")) > 0 {

上下文存在但不返回任何内容。

我已经调查了 mappingModels,但这似乎要求我们能够访问旧数据才能对其进行映射,目前新应用中没有可用的旧数据。

似乎没有太多关于在代码库之间迁移 CoreData 的信息,而是专注于更新您正在使用的数据库的版本。

我尝试了什么:

  • 我已验证 CoreData 没有被添加到顶部的新应用程序删除。当我重新加载旧应用时,数据仍然存在
  • 在测试时,我可以在两个项目之间访问相同的 UserDefaults,这再次让我放心,数据存在但未被访问
  • 在线调查迁移教程 - 所有这些似乎都集中在版本之间或同一代码库内部的迁移

感觉这应该比我做的容易

  1. 这甚至可能吗? - 我们是否必须使用 same 数据库 - 因为我们只能在原始代码库中执行此操作,因为即使旧数据库的副本也不同
  2. 我只是在配置方面做错了吗 - 数据库是否链接到项目名称或两个项目之间不同的其他内容。

让这件事变得更棘手的一个问题是我们没有任何空间来修改旧代码 - 我们只需要编写新代码来迁移旧代码。

编辑 1: 在我的调查中,我注意到两个项目数据库的代码生成是不同的——旧项目中的 Objective-C 和新项目中的 swift。当我最初导入OldData 时,它仍然是Objective-C 代码生成。一旦我将它切换到 swift 旧数据库开始出现,但保存的对象仍然没有出现在我的提取中。

我不确定这是否是由语言代码生成差异引起的问题

编辑 2: 在进行一些测试后,使用不同的代码生成器语言似乎不会导致任何问题。

但我确实注意到 SQL 数据库存储在不同的位置:

旧的存储在Documents 文件夹中,新的存储在Application Support 文件夹中。相关文章here

中提到了一些变化

这意味着问题可能是我们将两个 SQL 文件放在不同的位置,这意味着数据库不是使用旧的,而是创建一个新的空文件。

我将继续关注如何在配置时将新应用中的旧数据库指向不同的位置。

【问题讨论】:

    标签: ios swift core-data core-data-migration


    【解决方案1】:

    所以我最终找到了问题的原因并粗略的解决了。

     private func migrateOldDatabase() {
         if let documentsPath = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first {
         // We need to migrate the three old sql files into the new store location
         let pathSuffixToMigrate = ["Metlink.sqlite", "Metlink.sqlite-shm", "Metlink.sqlite-wal"]
    
         let fileManager = FileManager.default
    
         for suffix in pathSuffixToMigrate {
             let path = documentsPath.appendingPathComponent(suffix)
             if fileManager.fileExists(atPath: path.path) {
                let applicationStorePath = documentsPath.appendingPathComponent("Application Support")
    
                do {
                    let newCoredataMetlinkLocation = applicationStorePath.appendingPathComponent(suffix)
                    // If there is already the same file we delete it to ensure we migrate the one we want
                    if fileManager.fileExists(atPath: newCoredataMetlinkLocation.path) {
                        try fileManager.removeItem(at: newCoredataMetlinkLocation)
                    }
                    // We then copy the new one into its place
                    try fileManager.copyItem(at: path, to: newCoredataMetlinkLocation)
                } catch {
                    print("error")
                }
            }
        }
    }
    

    我们称它为 BEFORE 我们获取持久容器。

    migrateOldDatabase()
    let metlinkCoreDataManager = CoreDataManager(modelName: "Metlink")
    let metlinkDBcontext = metlinkCoreDataManager.persistentContainer.viewContext
    

    我将简要解释发生了什么。

    似乎以前 CoreData 存储在 Library 文件夹中。现在虽然它默认存储在库文件夹中的应用程序支持文件夹中。这意味着当我尝试迁移系统时,系统会查找旧数据库,但找不到它,因此会在应用程序支持中创建一个新的空数据库。

    我们在这里所做的是检查我们是否在旧位置有一个,并将所有三个 sql 文件复制到新位置(同时删除旧的,如果有的话)。我发现如果我们只复制一个,就会出现问题。

    我们可以在这里看到这个:

    您可以看到我的新数据库,然后我们手动将数据迁移到其中。

    我完全清楚,硬编码位置不是最佳解决方案,因此不建议将其作为第一种尝试方法。在我的情况下,我们只是在用户第一次加载新应用时尝试迁移,这意味着它不会持续存在危险。

    值得注意的是,几乎可以肯定有比上述解决方案更正确的解决方案。我发现这篇非常有用的文章 here 如果您想更改 coredata 数据库的位置,这几乎肯定是正确的方法。不幸的是,由于旧版本的 coredata 导致位置不同,我无法让它工作。

    【讨论】:

      猜你喜欢
      • 2017-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多