我已阅读名为Core Data Model Versioning and Data Migration Programming Guide的文件。但我仍然没有得到很多这方面的技能。所以我想张贴一个我见过的例子。
我有两个实体Rule
和Instance
。
Rule
有一个名为identifier
的属性。
Instance
还有一个名为identifier
的属性。
每个Rule
都有一个唯一标识符,每个实例的identifier
与Rules
的{{1}}相同。这就像Rule
和Instance
之间的多对多关系(它应该是)。
在我的数据模型的新版本中,我想在Rule
和Instance
之间建立多对多的关系,我该如何进行迁移?
答案 0 :(得分:5)
我已经弄清楚了。 首先,在创建持久性存储协调器时设置这些选项:
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
}
使用Xcode创建映射模型,设置其源版本和目标版本。
创建NSEntityMigrationPolicy的子类,将其命名为MyPolicy
,覆盖该方法。
-(BOOL)createRelationshipsForDestinationInstance:(NSManagedObject *)dInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
调用此方法时,所有托管对象都已在目标上下文中创建,但它们的关系不是。 在此方法中,检查dInstance是哪个实体,并为其建立关系。
使用Xcode,在映射模型中,将名为InstanceToInstance
的映射策略的ENTITY MAPPINGS设置为MyPolicy
。
将为每个Instance对象调用此方法一次。 对于我的问题,我应该这样做:
-(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;
}
然后,当应用程序启动时,将创建规则和实例之间的关系。
另请注意,由NSEntityMigrationPolicy的子类创建的关系不需要在xcode的迁移策略编辑窗口中设置值表达式,只需将其留空即可。
答案 1 :(得分:3)
您似乎可以使用轻量级迁移进行关系更改。
创建新版本后,只需更改或添加关系。
有关详细信息,请查看LightweightMigration
您需要做的就是将该选项添加到代理中的persistentStoreCoordinator方法。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"YOURDB.sqlite"]];
// handle db upgrade
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Handle error
}
return persistentStoreCoordinator;
}
然后,在您更改模型并将其选为活动模式后,只需重新安装您的应用程序即可。 就是这样。