增量数据文件(存在于sqlite后备存储中)使用与捆绑包中附带的数据相同的xcdatamodel版本;对象模型有零个变化.增量数据文件作为gzip压缩的sqlite文件从我们的服务器下载.我们不想通过运送应用程序的增量内容来膨胀我们的应用程序包.此外,我们不想依赖Webservice查询(因为复杂的数据模型).
我们已经从我们的服务器测试了增量sqlite数据的下载.我们已经能够将下载的数据存储添加到应用程序的sharedStoreCoordinator中.
{ NSError *error = nil; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption,[NSNumber numberWithBool:YES],NSInferMappingModelAutomaticallyOption,nil]; if (![__persistentStoreCoordinator addPersistentStoreWithType:NSsqliteStoreType configuration:nil URL:defaultStoreURL options:options error:&error]) { NSLog(@"Failed with error: %@",[error localizedDescription]); abort(); } // Check for the existence of incrementalStore // Add incrementalStore if (incrementalStoreExists) { if (![__persistentStoreCoordinator addPersistentStoreWithType:NSsqliteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error]) { NSLog(@"Add of incrementalStore Failed with error: %@",[error localizedDescription]); abort(); } } }
但是,这样做有两个问题.
>数据提取结果(例如,与NSFetchResultController)显示
来自incrementalStoreURL的数据附加到末尾
来自defaultStoreURL的数据.
>一些对象被重复.有很多实体
数据模型中的只读数据;当我们添加时,这些重复
第二个persistentStore到persistentStoreCoordinator.
理想情况下,我们希望Core Data将两个持久性存储的对象图合并成一个(在数据下载时,两个存储区的数据之间没有共享关系).此外,我们想删除重复的对象.
搜索网络时,我们看到了一些人试图做同样的事情,例如this answer和this answer.我们已经阅读了Marcus Zarra’s blog on importing large data sets in Core Data.但是,我们看不到任何解决方案为我们工作.我们不想手动将数据从增量存储读取并保存到默认存储,因为我们认为这将非常慢,并且在手机上容易出错.是否有更有效的合并方式?
我们已经尝试通过实现手动迁移来解决问题,如下所示.但是,我们未能成功地实现合并.我们对上面提到的答案1和2建议的解决方案并不清楚. Marcus Zarra的博客介绍了我们在将我们的大型数据集导入iOS的项目开始时所遇到的一些问题.
{ NSError *error = nil; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES],nil]; NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:__managedObjectModel destinationModel:__managedObjectModel]; if (![migrator migrateStoreFromURL:stateStoreURL type:NSsqliteStoreType options:options withMappingModel:nil toDestinationURL:destinationStoreURL destinationType:NSsqliteStoreType destinationOptions:nil error:&error]) { NSLog(@"%@",[error userInfo]); abort(); } }
看来,答案1的作者最后从增量存储中读取数据并将其保存到默认存储.也许,我们误解了第1条和第1条建议的解决方案. 2.我们的数据大小可能导致我们无法手动读取和重新插入增量数据到默认存储.我的问题是:从两个persistentStores(具有相同的objectModel)获取对象图的最有效的方法是将其合并到一个persistentStore中是什么?
当我们向对象图添加新的实体属性或修改关系时,自动迁移工作得很好.是否有一个简单的解决方案来将类似的数据合并到相同的持久性存储中,这将有足够的弹性来停止和恢复 – 自动迁移完成?
解决方法
例如,我的数据模型中有“国家”和“国家”的实体.我需要在对象图中只有一个国家和州的实例.我把这些实体保留在增量存储中,并且仅在默认存储中创建它们.我使用Fetched Properties松开链接我的主体图形到这些实体.我在模型中创建了所有实体实例的默认存储.增量存储在数据创建完成后,没有只读实体(即我的情况下的国家和州)开始或删除它们.
下一步是在应用程序启动期间将增量存储添加到自己的persistentStoreCoordinator(与要迁移所有内容的默认存储的协调器不同).
最后一步是在增量存储上调用migratePersistentStore方法将其数据合并到主(即默认)存储.普雷斯托!
以下代码片段说明了上面提到的最后两个步骤.我做了这些步骤,使我的设置将增量数据合并到主数据存储工作.
{ NSError *error = nil; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES],nil]; if (![__persistentStoreCoordinator addPersistentStoreWithType:NSsqliteStoreType configuration:nil URL:defaultStoreURL options:options error:&error]) { NSLog(@"Failed with error: %@",[error localizedDescription]); abort(); } // Check for the existence of incrementalStore // Add incrementalStore if (incrementalStoreExists) { NSPersistentStore *incrementalStore = [_incrementalPersistentStoreCoordinator addPersistentStoreWithType:NSsqliteStoreType configuration:nil URL:incrementalStoreURL options:options error:&error]; if (!incrementalStore) { NSLog(@"Unresolved error %@,%@",error,[error userInfo]); abort(); } if (![_incrementalPersistentStoreCoordinator migratePersistentStore:incrementalStore toURL:_defaultStoreURL options:options withType:NSsqliteStoreType error:&error]) { NSLog(@"%@",[error userInfo]); abort(); } // Destroy the store and store coordinator for the incremental store [_incrementalPersistentStoreCoordinator removePersistentStore:incrementalStore error:&error]; incrementalPersistentStoreCoordinator = nil; // Should probably delete the URL from file system as well // } }