Objective c 合并两个iOS核心数据持久存储的有效方法是什么?
在我们正在开发的应用程序中,我们使用核心数据和sqlite支持存储来存储我们的数据。我们应用程序的对象模型很复杂。此外,我们的应用程序提供的数据总量太大,无法装入iOS(iPhone/iPad/iPod Touch)应用程序包。由于我们的用户通常只对数据的一个子集感兴趣,因此我们对数据进行了分区,以便应用程序附带应用程序包中数据对象的一个子集(尽管约100 MB)。我们的用户在通过iTunes应用内购买支付额外内容后,可以选择从我们的服务器下载额外的数据对象(大小约5 MB到100 MB)。 增量数据文件(存在于sqlite备份存储中)使用与捆绑包附带的数据相同的xcdatamodel版本;对象模型没有任何更改。增量数据文件作为gzip sqlite文件从我们的服务器下载。我们不想通过将增量内容与应用程序一起交付而使我们的应用程序包膨胀。此外,我们不希望依赖于webservice上的查询(因为复杂的数据模型)。 我们已经测试了从服务器下载的增量sqlite数据。我们已经能够将下载的数据存储添加到应用程序的共享persistentStoreCoordinator。 然而,这样做有两个问题Objective c 合并两个iOS核心数据持久存储的有效方法是什么?,objective-c,core-data,merge,core-data-migration,object-graph,Objective C,Core Data,Merge,Core Data Migration,Object Graph,在我们正在开发的应用程序中,我们使用核心数据和sqlite支持存储来存储我们的数据。我们应用程序的对象模型很复杂。此外,我们的应用程序提供的数据总量太大,无法装入iOS(iPhone/iPad/iPod Touch)应用程序包。由于我们的用户通常只对数据的一个子集感兴趣,因此我们对数据进行了分区,以便应用程序附带应用程序包中数据对象的一个子集(尽管约100 MB)。我们的用户在通过iTunes应用内购买支付额外内容后,可以选择从我们的服务器下载额外的数据对象(大小约5 MB到100 MB)。
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 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条和第2条提出的解决方案。数据的大小可能使我们无法手动读取增量数据并将其重新插入默认存储。我的问题是:从两个persistentStore(具有相同的objectModel)获取对象图合并到一个persistentStore中的最有效方法是什么
当我们向对象图添加新的实体属性或修改关系时,自动迁移效果非常好。有没有一个简单的解决方案可以将相似的数据合并到同一个持久存储中,这样就可以在自动迁移完成时,有足够的弹性停止并恢复 迁移不起作用的原因是托管对象模型相同 从技术上讲,您谈论的是“数据迁移”,而不是“模式迁移”。CoreData的迁移API设计用于模式迁移,即处理对托管对象模型的更改 至于将数据从一家商店传输到另一家商店,你需要依靠自己。CoreData可以通过对获取请求使用批处理和获取限制来帮助您提高效率,但您需要自己实现逻辑 听起来你有两个持久存储,一个大的和一个小的。加载较小的存储并对其进行分析,发现需要在较大的存储中查询的一组主键或唯一标识符,将是最有效的方法 然后,只需在较大的存储中查询这些标识符,就可以轻松地消除重复 NSFetchRequest的文档包含用于确定查询范围的API:
您不需要任何迁移—迁移旨在改变NSManagedObjectModel,而不是数据本身 您真正需要的是一个管理两个持久存储的持久存储协调器。这有点棘手,但不是太难,真的 有一个类似的问题,可以解释你,你真正需要做什么。 这是马库斯·扎拉写的一篇好文章
经过几次尝试,我终于想出了如何使这项工作正常进行。秘密在于首先创建增量存储数据,而不为只读实体创建任何数据。在增量存储中不保留只读数据的情况下,这些实体实例的实体实例将在数据迁移和合并后被复制。因此,应在不使用这些只读实体的情况下创建增量存储。默认存储区将是唯一拥有它们的存储区 例如,我的数据模型中有实体“国家”和“州”。我只需要在我的对象图中有一个Country和State实例。我将这些实体排除在增量存储之外,并仅在默认存储中创建它们。我使用获取的属性将我的主对象图松散地链接到这些实体。我使用模型中的所有实体实例创建了默认存储。增量存储要么没有只读实体(在我的例子中是国家和州),要么在数据创建完成后将其删除
{
NSError *error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 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();
}
}
{
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) {
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
//
}
}