Core Data 轻量级迁移

如果只是简单的改变模型,比如给一个实体添加一个新属性, Core Data 可以自动进行数据迁移,也就是指轻量级迁移。轻量级迁移基本上和普通迁移是一样的,不过不需要提供映射模型,(在映射概况中有介绍),Core Data自行推断新模型和目标模型的差异。

轻量级迁移在应用开发的早期阶段使用非常方便,当你频繁的改变对象模型,但是又不想重新生成测试数据的时候。你可以迁移已存在的数据,不需要为每个模型重新创建一个映射模型,用来创建迁移需要的store。

另一个好处是,当你使用推测模型(inferred model)和 SQLite 存储时,Core Data 可以执行就地(in situ)迁移,严格讲,直接生成并执行 SQL 语句。因为没有载入任何数据,所以能很多程度上提升性能。因此,推荐你尽可能的使用推测模型,即使需要创建映射模型。

Core Data 必须能推测出映射关系

执行自动化迁移,Core Data 需要能够在运行时找到源和目标的映射关系,一般我们将数据模型存放在 bundles文件夹中(使用 NSBundle 的 allBundles 和 allFrameworks 方法获得)Core Data可以找到并发现它,如果放在别的地方,需要按照  “Use a Migration Manager if Models Cannot Be Found Automatically .” 中说的步骤操作。Core Data 随后自动分析现有表和字段的变化,自动产生推测的映射模型(inferred mapping model)。

以下几种情况,Core Data 可以自动推测出:

  • 添加新属性/字段

  • 删除属性/字段

  • 必填属性/字段改为可选属性/字段

  • 可选属性/字段改为必填属性/字段,并设置默认值

  • 重命名实体/表或属性/字段

如果要重命名,需要将新版本中新实体/属性的“重命名标识符”(renaming identifier)的值设置为原来的实体名或属性名。具体方法:Xcode Data Modeling 工具->属性查看器(property inspector)。

比如你可以:

重命名一个 Car 实体为Automobile

重命名一个Car的color属性为paintColor

可以想象,这样做以后,如一个属性的名字在三次修改中都变化了,且都标记了重命名标识符,这样不管是从 version 2 到 version 3 还是从 version 1 到 version 3 都可以无错误的迁移。

另外,Core Data 还可以自动猜测出:

  • 增加关系relationship)和 改变关系类型

    • 增加新关系,删除现有关系

    • 重命名关系名称 (同样设置重命名标识符,同重命名属性一样)

    • 改变关系由对一到对多,或者a non-ordered to-many to ordered (反之亦然)

  • 改变实体/表的体系结构

    • 增加、删除、重命名实体/表

    • 增加新的父、子实体/表,移动属性/字段的顺序

    • 将实体/表移出体系

      注意,不能整合(merge)两个实体体系(如果两个实体在原模型中不是共享一个父类实体,那么目标模型中也不能共享一个父类实体)

使用选项字典(Options Dictionary)请求自动迁移(Automatic Migration)


通过定义选项字典请求自动轻量级迁移,将 NSMigratePersistentStoresAutomaticallyOption 和 NSInferMappingModelAutomaticallyOption 两个键值设置为YES,然后调用 addPersistentStoreWithType:configuration:URL:options:error:

You request automatic lightweight migration using the options dictionary you pass inaddPersistentStoreWithType:configuration:URL:options:error:, by setting values corresponding to both the NSMigratePersistentStoresAutomaticallyOption and theNSInferMappingModelAutomaticallyOption keys to YES:

NSError *error = nil;
NSURL *storeURL = <#The URL of a persistent store#>;
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
 
BOOL success = [psc addPersistentStoreWithType:<#Store type#>
                    configuration:<#Configuration or nil#> URL:storeURL
                    options:options error:&error];
if (!success) {
    // Handle the error.
}

可以使用 NSMappingModel 的 inferredMappingModelForSourceModel:destinationModel:error: 方法,获取推测的映射模型,如果可以推测出返回,如果不可以,返回 nil。

如果不能自动找到模型,则使用迁移管理器(Migration Manager)

执行自动迁移,必须保证 Core Data 能够在运行时找到源对象模型和目标对象模型,如果你需要将模型存放于自动搜索范围之外,那么需要我们自己生成推测的模型,并实例化迁移管理器(NSMigrationManager)。如下面的代码,这些代码假设已经实现了 sourceModel 和 destinationModel,这两个方法分别返回源对象和目标对象。
- (BOOL)migrateStore:(NSURL *)storeURL toVersionTwoStore:(NSURL *)dstStoreURL error:(NSError **)outError {
 
    // Try to get an inferred mapping model.
    NSMappingModel *mappingModel =
        [NSMappingModel inferredMappingModelForSourceModel:[self sourceModel]
                        destinationModel:[self destinationModel] error:outError];
 
    // If Core Data cannot create an inferred mapping model, return NO.
    if (!mappingModel) {
        return NO;
    }
 
    // Create a migration manager to perform the migration.
    NSMigrationManager *manager = [[NSMigrationManager alloc]
        initWithSourceModel:[self sourceModel] destinationModel:[self destinationModel]];
 
    BOOL success = [manager migrateStoreFromURL:storeURL type:NSSQLiteStoreType
        options:nil withMappingModel:mappingModel toDestinationURL:dstStoreURL
        destinationType:NSSQLiteStoreType destinationOptions:nil error:outError];
 
    return success;
}

Note:  OS X v10.7 and iOS 4之前,需要使用 store-specific migration manager执行轻量化迁移,你通过已存在的 persistent store来获得 migration manager,使用migrationManagerClass,如下面示例展示的

- (BOOL)migrateStore:(NSURL *)storeURL toVersionTwoStore:(NSURL *)dstStoreURL error:(NSError **)outError {
 
    // Try to get an inferred mapping model.
    NSMappingModel *mappingModel =
        [NSMappingModel inferredMappingModelForSourceModel:[self sourceModel]
                        destinationModel:[self destinationModel] error:outError];
 
    // If Core Data cannot create an inferred mapping model, return NO.
    if (!mappingModel) {
        return NO;
    }
 
    // Get the migration manager class to perform the migration.
    NSValue *classValue =
        [[NSPersistentStoreCoordinator registeredStoreTypes] objectForKey:NSSQLiteStoreType];
    Class sqliteStoreClass = (Class)[classValue pointerValue];
    Class sqliteStoreMigrationManagerClass = [sqliteStoreClass migrationManagerClass];
 
    NSMigrationManager *manager = [[sqliteStoreMigrationManagerClass alloc]
        initWithSourceModel:[self sourceModel] destinationModel:[self destinationModel]];
 
    BOOL success = [manager migrateStoreFromURL:storeURL type:NSSQLiteStoreType
        options:nil withMappingModel:mappingModel toDestinationURL:dstStoreURL
        destinationType:NSSQLiteStoreType destinationOptions:nil error:outError];
 
    return success;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值