"Can't add the same store twice" 关于核心数据版本的迁移
"Can't add the same store twice" on migration of Core Data versions
我正在尝试在两个版本的 CoreData 之间执行迁移,这两个版本的根本区别在于新版本有两个配置,因此我可以将实体保存在两个不同的 sqlite 文件中(一个在 Main Bundle 中是只读的,另一个是,旧的 sqlite,现在仅用于用户数据)。我还添加了一个模型映射来映射差异,特别是重置由于多个配置而丢失的实体之间的关系。
如果从头开始安装并且新记录按预期插入到应用程序文档目录中的用户数据 sqlite 中,则该应用程序可以正常运行而不会崩溃。
问题是当我尝试从以前的 Core Data 版本迁移时:应用程序启动时没有崩溃,但首先 executeFetchRequest
它在 coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Userdata", URL: urlUser, options: optionsUser, error: &errorUser)
崩溃(使用调试查看)和控制台 return 此日志:
2015-02-23 18:48:24.052 MedAbility[21480:585606] CoreData: error:
-addPersistentStoreWithType:SQLite configuration:(null) URL:file:///Volumes/Documenti/Users/andrea/Library/Developer/CoreSimulator/Devices/301801BE-4B6A-4371-BE66-3E71557B0897/data/Containers/Data/Application/FBEC0124-1D74-4F94-99F2-6F492281AA8E/Documents/MedAbility.sqlite
options:{
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1; } ... returned error Error Domain=NSCocoaErrorDomain Code=134080 "The operation
couldn’t be completed. (Cocoa error 134080.)" UserInfo=0x7fb50ae481d0
{NSUnderlyingException=Can't add the same store twice} with userInfo
dictionary {
NSUnderlyingException = "Can't add the same store twice"; } 2015-02-23 18:48:24.061 MedAbility[21480:585606] CoreData: error:
-addPersistentStoreWithType:SQLite configuration:Userdata URL:file:///Volumes/Documenti/Users/andrea/Library/Developer/CoreSimulator/Devices/301801BE-4B6A-4371-BE66-3E71557B0897/data/Containers/Data/Application/FBEC0124-1D74-4F94-99F2-6F492281AA8E/Documents/MedAbility.sqlite
options:{
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1; } ... returned error Error Domain=NSCocoaErrorDomain Code=134080 "The operation
couldn’t be completed. (Cocoa error 134080.)" UserInfo=0x7fb50ae481d0
{NSUnderlyingException=Can't add the same store twice} with userInfo
dictionary {
NSUnderlyingException = "Can't add the same store twice"; }
这是我的代码:
旧版本 PersistentStoreCoordinator:
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
// Create the coordinator and store
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("MedAbility.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
// Set options for migrations
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options, error: &error) == nil {
coordinator = nil
// Report any error we got.
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(error), \(error!.userInfo)")
}
// Exclude db from backup
Util.addSkipBackupAttributeToItemAtURL(url)
return coordinator
}()
新版本 PersistentStoreCoordinator:
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = NSBundle.mainBundle().URLForResource("MedAbilityDomande", withExtension: "sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
// Set questions sqlite as read-only
let options = [NSReadOnlyPersistentStoreOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Domande", URL: url, options: options, error: &error) == nil {
coordinator = nil
// Report any error we got.
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(error), \(error!.userInfo)")
}
let urlUser = self.applicationDocumentsDirectory.URLByAppendingPathComponent("MedAbility.sqlite")
var errorUser: NSError? = nil
var failureReasonUser = "There was an error creating or loading the application's saved data."
// Set migration options
let optionsUser = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Userdata", URL: urlUser, options: optionsUser, error: &errorUser) == nil {
coordinator = nil
// Report any error we got.
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReasonUser
dict[NSUnderlyingErrorKey] = errorUser
errorUser = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(errorUser), \(errorUser!.userInfo)")
}
return coordinator
}()
有人知道我该如何解决这个问题吗?
感谢您的帮助!
编辑
我做了一些测试,发现为第一个数据库评论 coordinator!.addPersistentStoreWithType (NSSQLiteStoreType, configuration: "Questions", URL: url, options: options, error: & error)
,应用程序启动没有问题,显然没有添加数据库的内容。如果我反转两个数据库的添加,应用程序会崩溃并显示相同的日志,除了 "URL: file:[...]" 它是在前一个现在第二个数据库 ("MedAbilityDomande.sqlite") 上调用的;实际上,问题是第二个数据库的添加,而不是特定的数据库。似乎将旧数据库迁移到用于用户数据的新数据库实际上并没有迁移配置,因此仍然是与插入到 mainBundle 中的新只读数据库重叠实体的旧配置。正如我之前所说,如果该应用程序从头开始(无需迁移)就可以完美运行。
你有什么想法吗?
再次感谢您!
我终于找到解决办法了!我根据要迁移后用于用户数据的数据库创建了数据库MedAbilityDomande.sqlite
。这导致有两个具有相同 UUID 的数据库生成错误 "Can't add the same store twice"
。更改应用程序包中数据库的 UUID 就足够了 (MedAbilityDomande.sqlite),一切都很好。
下次见!
我正在尝试在两个版本的 CoreData 之间执行迁移,这两个版本的根本区别在于新版本有两个配置,因此我可以将实体保存在两个不同的 sqlite 文件中(一个在 Main Bundle 中是只读的,另一个是,旧的 sqlite,现在仅用于用户数据)。我还添加了一个模型映射来映射差异,特别是重置由于多个配置而丢失的实体之间的关系。
如果从头开始安装并且新记录按预期插入到应用程序文档目录中的用户数据 sqlite 中,则该应用程序可以正常运行而不会崩溃。
问题是当我尝试从以前的 Core Data 版本迁移时:应用程序启动时没有崩溃,但首先 executeFetchRequest
它在 coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Userdata", URL: urlUser, options: optionsUser, error: &errorUser)
崩溃(使用调试查看)和控制台 return 此日志:
2015-02-23 18:48:24.052 MedAbility[21480:585606] CoreData: error: -addPersistentStoreWithType:SQLite configuration:(null) URL:file:///Volumes/Documenti/Users/andrea/Library/Developer/CoreSimulator/Devices/301801BE-4B6A-4371-BE66-3E71557B0897/data/Containers/Data/Application/FBEC0124-1D74-4F94-99F2-6F492281AA8E/Documents/MedAbility.sqlite options:{ NSInferMappingModelAutomaticallyOption = 1; NSMigratePersistentStoresAutomaticallyOption = 1; } ... returned error Error Domain=NSCocoaErrorDomain Code=134080 "The operation couldn’t be completed. (Cocoa error 134080.)" UserInfo=0x7fb50ae481d0 {NSUnderlyingException=Can't add the same store twice} with userInfo dictionary { NSUnderlyingException = "Can't add the same store twice"; } 2015-02-23 18:48:24.061 MedAbility[21480:585606] CoreData: error: -addPersistentStoreWithType:SQLite configuration:Userdata URL:file:///Volumes/Documenti/Users/andrea/Library/Developer/CoreSimulator/Devices/301801BE-4B6A-4371-BE66-3E71557B0897/data/Containers/Data/Application/FBEC0124-1D74-4F94-99F2-6F492281AA8E/Documents/MedAbility.sqlite options:{ NSInferMappingModelAutomaticallyOption = 1; NSMigratePersistentStoresAutomaticallyOption = 1; } ... returned error Error Domain=NSCocoaErrorDomain Code=134080 "The operation couldn’t be completed. (Cocoa error 134080.)" UserInfo=0x7fb50ae481d0 {NSUnderlyingException=Can't add the same store twice} with userInfo dictionary { NSUnderlyingException = "Can't add the same store twice"; }
这是我的代码:
旧版本 PersistentStoreCoordinator:
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
// Create the coordinator and store
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("MedAbility.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
// Set options for migrations
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options, error: &error) == nil {
coordinator = nil
// Report any error we got.
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(error), \(error!.userInfo)")
}
// Exclude db from backup
Util.addSkipBackupAttributeToItemAtURL(url)
return coordinator
}()
新版本 PersistentStoreCoordinator:
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = NSBundle.mainBundle().URLForResource("MedAbilityDomande", withExtension: "sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
// Set questions sqlite as read-only
let options = [NSReadOnlyPersistentStoreOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Domande", URL: url, options: options, error: &error) == nil {
coordinator = nil
// Report any error we got.
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(error), \(error!.userInfo)")
}
let urlUser = self.applicationDocumentsDirectory.URLByAppendingPathComponent("MedAbility.sqlite")
var errorUser: NSError? = nil
var failureReasonUser = "There was an error creating or loading the application's saved data."
// Set migration options
let optionsUser = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "Userdata", URL: urlUser, options: optionsUser, error: &errorUser) == nil {
coordinator = nil
// Report any error we got.
let dict = NSMutableDictionary()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReasonUser
dict[NSUnderlyingErrorKey] = errorUser
errorUser = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSLog("Unresolved error \(errorUser), \(errorUser!.userInfo)")
}
return coordinator
}()
有人知道我该如何解决这个问题吗?
感谢您的帮助!
编辑
我做了一些测试,发现为第一个数据库评论 coordinator!.addPersistentStoreWithType (NSSQLiteStoreType, configuration: "Questions", URL: url, options: options, error: & error)
,应用程序启动没有问题,显然没有添加数据库的内容。如果我反转两个数据库的添加,应用程序会崩溃并显示相同的日志,除了 "URL: file:[...]" 它是在前一个现在第二个数据库 ("MedAbilityDomande.sqlite") 上调用的;实际上,问题是第二个数据库的添加,而不是特定的数据库。似乎将旧数据库迁移到用于用户数据的新数据库实际上并没有迁移配置,因此仍然是与插入到 mainBundle 中的新只读数据库重叠实体的旧配置。正如我之前所说,如果该应用程序从头开始(无需迁移)就可以完美运行。
你有什么想法吗?
再次感谢您!
我终于找到解决办法了!我根据要迁移后用于用户数据的数据库创建了数据库MedAbilityDomande.sqlite
。这导致有两个具有相同 UUID 的数据库生成错误 "Can't add the same store twice"
。更改应用程序包中数据库的 UUID 就足够了 (MedAbilityDomande.sqlite),一切都很好。
下次见!