核心数据迁移 [英] core data migration by example
问题描述
我阅读了名为的文档核心数据模型版本化和数据迁移编程指南 。但我还是没有得到很多技能。
我有两个实体 Rule
和实例
。
Rule
有一个名为 identifier
的属性。
实例
也有一个名为 identifier
的属性。
每个规则
都有一个唯一的标识符,每个实例都有标识符
与 Rules
。它像 Rule
和 Instance
(应该是)之间的许多关系。
在我的数据模型的新版本中,我想在 Rule
和 Instance
,我如何做迁移?
首先,创建持久存储协调器时设置这些选项:
NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES],NSInferMappingModelAutomaticallyOption,
nil];
if(![__ persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:options error:& error])
{
/ /其他代码句柄错误
}
使用Xcode创建映射模型,和目标版本。
创建NSEntityMigrationPolicy的子类,将其命名为 MyPolicy
,覆盖该方法。 (NSMigrationManager *)管理器错误:(NSMigrationManager *)管理器错误:(NSMigrationManager *)管理器错误:(NSMigrationManager *)管理器错误:(NSMigrationManager * *)错误
当调用此方法时,所有managedObject都已在目标上下文中创建,关系不是。
在此方法中,检查什么实体是dInstance,并为它建立关系。
使用Xcode,在映射模型中,设置ENTITY MAPPINGS命名为 InstanceToInstance
的映射政策为 MyPolicy
。
将为每个实例对象调用一次。
我的问题,我应该这样做:
- (BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping: (NSEntityMapping *)映射管理器:(NSMigrationManager *)管理器错误:(NSError **)错误{
NSError * superError = nil;
BOOL mappingSuccess = [super createRelationshipsForDestinationInstance:dInstance entityMapping:mapping manager:manager error:& superError];
if([dInstance.entity.name isEqualToString:@Rule]){
Instance * instance =(Instance *)dInstance;
NSFetchRequest * fetch = [[NSFetchRequest alloc] initWithEntityName:@Instance];
fetch.predicate = [NSPredicate predicateWithFormat:@identifier ==%@,instance.identifier];
NSArray * result = [manager.destinationContext executeFetchRequest:fetch];
Rule * rule = [result objectAtIndex:0];
instance.rule = rule;
}
return YES;
}
然后,应用程式启动时会建立Rule和Instance 。
另请注意,NSEntityMigrationPolicy子类创建的关系不需要在xcode的迁移策略编辑窗口中设置值表达式,只需将其留空即可。
I've read the document named Core Data Model Versioning and Data Migration Programming Guide. But I still don't get many skills on this. So I want to post an example I met.
I have two entities Rule
and Instance
.
Rule
has an attribute named identifier
.
Instance
also has an attribute named identifier
.
every Rule
has an unique identifier and every instance have an identifier
the same to one of Rules
. It is like a to many relationship between Rule
and Instance
(and it should be).
In new version of my data model, I want to make a to-many relationship between Rule
and Instance
, how do I do the migration?
I've figured it out. first, set these options when creating persistent store coordinator:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:options error:&error])
{
//other code handle error
}
Create a mapping model with Xcode, setting its source version and destination version.
Make a subclass of NSEntityMigrationPolicy,name it MyPolicy
, overwrite the method.
-(BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
when this method is invoked, all the managedObjects has been create in destination context, but their relationships are not. In this method, check what entity is the dInstance, and make relation for it.
With Xcode,in your mapping model, set The ENTITY MAPPINGS named InstanceToInstance
's mapping policy to MyPolicy
.
this method will be called once for each Instance object. for my question, I should do this:
-(BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error{
NSError *superError = nil;
BOOL mappingSuccess = [super createRelationshipsForDestinationInstance:dInstance entityMapping:mapping manager:manager error:&superError];
if ([dInstance.entity.name isEqualToString:@"Rule"]){
Instance *instance = (Instance*)dInstance;
NSFetchRequest *fetch = [[NSFetchRequest alloc] initWithEntityName:@"Instance"];
fetch.predicate = [NSPredicate predicateWithFormat:@"identifier == %@",instance.identifier];
NSArray *result = [manager.destinationContext executeFetchRequest:fetch];
Rule *rule = [result objectAtIndex:0];
instance.rule = rule;
}
return YES;
}
Then, the relation ship between Rule and Instance will be created when the app launches.
Also notice, relationships created by subclass of NSEntityMigrationPolicy don't need to set the value expression in xcode's migration policy editing window, just leave it blank.
这篇关于核心数据迁移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!