2

我已经阅读了名为Core Data Model Versioning and Data Migration Programming Guide的文档。但我仍然没有得到很多这方面的技能。所以我想发布一个我遇到的例子。

我有两个实体RuleInstance. Rule有一个名为 的属性identifierInstance还有一个名为identifier.

每个Rule都有一个唯一的标识符,每个实例都identifier与其中之一相同RulesRule这就像和Instance(应该是)之间的多对多关系。

在我的数据模型的新版本中,我想在 和 之间建立一对多的关系RuleInstance我该如何进行迁移?

4

2 回答 2

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

调用此方法时,所有 managedObjects 都已在目标上下文中创建,但它们的关系不是。在此方法中,检查 dInstance 是什么实体,并为其建立关系。

使用 Xcode,在您的映射模型中,将 ENTITY MAAPPINGS 命名InstanceToInstance的映射策略设置为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;
}

然后,应用程序启动时将创建 Rule 和 Instance 之间的关系。

还要注意,由 NSEntityMigrationPolicy 的子类创建的关系不需要在 xcode 的迁移策略编辑窗口中设置值表达式,只需将其留空即可。

于 2012-12-26T06:51:52.857 回答
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;
}

然后,在您更改模型并将其选择为活动后,只需重新安装您的应用程序。就这样。

于 2012-12-17T09:12:46.053 回答