Swift 核心数据迁移崩溃:"SELECT MAX(Z_PK) FROM (null)" 中的语法错误

Swift Core Data Migration Crash : syntax error in "SELECT MAX(Z_PK) FROM (null)"

我正在通过一个测试项目试用 Core Data,但我在 Core Data 和迁移方面遇到了一些问题。轻量级自动迁移过程中,出现如下crash:

 [logging] near "null": syntax error in "SELECT MAX(Z_PK) FROM (null)"



[error] error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (134110)
CoreData: error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (134110)
CoreData: annotation: userInfo:
CoreData: annotation:   sourceURL : file:///var/mobile/Containers/Data/Application/D712273A-6E49-4B19-9919-3E55F6A5A37D/Library/Application%20Support/TestApp.sqlite
CoreData: annotation:   reason : Cannot migrate store in-place: near "null": syntax error
CoreData: annotation:   destinationURL : file:///var/mobile/Containers/Data/Application/D712273A-6E49-4B19-9919-3E55F6A5A37D/Library/Application%20Support/TestApp.sqlite
CoreData: annotation:   NSUnderlyingError : Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration." UserInfo={reason=near "null": syntax error, NSSQLiteErrorDomain=1, NSUnderlyingException=near "null": syntax error}
CoreData: annotation: storeType: SQLite
CoreData: annotation: configuration: (null)
CoreData: annotation: URL: file:///var/mobile/Containers/Data/Application/D712273A-6E49-4B19-9919-3E55F6A5A37D/Library/Application%20Support/TestApp.sqlite
CoreData: annotation: options:
CoreData: annotation:   NSInferMappingModelAutomaticallyOption : 1
CoreData: annotation:   NSMigratePersistentStoresAutomaticallyOption : 1
CoreData: annotation:   NSPersistentStoreFileProtectionKey : NSFileProtectionComplete
CoreData: annotation: <NSPersistentStoreCoordinator: 0x281cf1500>: Attempting recovery from error encountered during addPersistentStore: Error Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration."

这是用于在 SwiftUI 应用程序中加载数据库的 PersistenceCointainer 代码:

struct PersistenceController {
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        for _ in 0..<10 {
            let newItem = Relation(context: viewContext)
            newItem.date = Date()
        }
        do {
            try viewContext.save()
        } catch {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()

    var container: NSPersistentContainer

    init(inMemory: Bool = false) {
        container = NSPersistentContainer(name: "TestApp")
        
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        
        if let storeDirectory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first {
                let sqliteURL = storeDirectory.appendingPathComponent("TestApp.sqlite")
                
                //Set Protection for Core data sql file
                let description = NSPersistentStoreDescription(url: sqliteURL)
                description.shouldInferMappingModelAutomatically = true
                description.shouldMigrateStoreAutomatically = true
                description.setOption(FileProtectionType.complete as NSObject, forKey: NSPersistentStoreFileProtectionKey)
                container.persistentStoreDescriptions = [description]
            }
        
       
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                /*
                 Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
        
    }
    
    
}

这里有更多关于我要更改的模型的信息。我有一个名为“合作伙伴”的简单模型:

如有必要,我可以显示更多关系细节。

我只是添加了一个新的 String 可选属性,所以我认为轻量级迁移会很容易。

我已经创建了大量测试数据来尝试一些功能,我很乐意避免删除我的数据库 ^^ 而且由于这是一个测试项目,我想了解问题的来源以避免重复它.

任何人都可以帮助理解这个“SELECT MAX(Z_PK) FROM (null)”来自哪里以及我该如何解决它?

好的,所以我尝试深入数据库,但没有找到任何 strange-looking 数据。

我刚刚创建了一个从旧模型到新模型的映射模型 Partner,并指定新字段应采用“默认”值,并且迁移有效:所以我想我永远不会知道这个错误的真正原因是什么:)

我对任何会遇到此错误的人的建议:尝试创建映射模型(this tutorial 中的步骤 7/8)