Core Data 模型版本升级和数据迁移

转自;http://my.oschina.net/zhmsong/blog/147920

Core Data 支持随着app开发演进而带来的对象模型(managed object model)升级或修改的管理。模型的改变将导致不兼容(或不能打开)以前版本创建的存储。如果你要改变你的模型,你就必须要改变现有存储中的数据-也就是数据存储格式(store format)-这被称为迁移(migration)。

要想迁移数据,你既需要原始版本,又需要当前版本。因此,需要创建 带版本的模型(versioned model),带版本的模型(像版本仓库)可以存储下多个版本。如果没有问题的话,Core Data 可以使用当前新版本打开以前版本创建的数据存储,并将其迁移至当前版本规范中。因此,为了帮助 Core Data 迁移,需要我们提供新旧版本间的映射信息(map),映射信息有两种方式,一是简单根据版本号,二是创建独立的映射模型文件(separate mapping model file)。 

通常程序版本改变,会涉及到很多方面,Core Data 没有能力为我们自动处理,但提供了一些技术为我们所用: 

  • 模型版本管理,方便区分不同阶段的不同版本。 

    模型版本,有两个视角,以程序员看,就是版本号(文字本身);从 Core Data角度看,就是另一回事,具体看 “Understanding Versions.”

    带版本的对象模型文件格式和如何添加版本号,参见 “Model File Format and Versions.”

  • 映射方式选择(表和字段/实体和属性) 

    简单情况下,Core Data 可以推测出(infer)如何映射,具体见“轻量级数据迁移” “Lightweight Migration.”

    如果复杂了,Core Data 无法推测,我们必须创建映射模型(mapping model),通过映射模型,表述如何转换(从旧版本到新版本),创建方法见  “Mapping Overview.”

  • 数据迁移的过程参见 “The Migration Process.”,如何执行具体的迁移参见 “Initiating the Migration Process.”

    可以定制迁移过程,如决定是否有必要进行迁移(if-else)、如何找到正确的源模型和目标模型(correct source and destination models)及正确的映射模型。 

    如果你要自己初始化迁移过程,那你只能自定迁移过程,比如,在主文件夹(main bundle)之外的位置搜索,或者,利用多个映射模型执行几个阶段的迁移,也可能在大数据集基础上处理。自定迁移过程参见  “Customizing the Migration Process.”

  • 使用了 iCloud 的App,只能执行轻量级迁移,具体参  “Migration and iCloud.”

尽管可以轻松完成,但还需谨慎,避免冲突。







  • 轻量级数据迁移(下称LM), Core Data 自动执行,适用模型简单改变(simple changes),包括:实体/表中增加新属性/字段,LM 与普通迁移原理完全一样,只是不需要映射模型(mapping model) (参见 “Mapping Overview”),Core Data 自行推测(infers)版本间的差异。
  • LM中 Core Data 必须能推测出映射关系
  • 使用选项字典(Options Dictionary)请求自动迁移(Automatic Migration)
  • 如果不能自动找到模型,则使用迁移管理器(Migration Manager)
  • 文章来源:developer.apple.com

    轻量级数据迁移(下称LM), Core Data 自动执行,适用模型简单改变(simple changes),包括:实体/表中增加新属性/字段,LM 与普通迁移原理完全一样,只是不需要映射模型(mapping model) (参见 “Mapping Overview”),Core Data 自行推测(infers)版本间的差异。


    LM 适用于APP早期开发,那时总是在改变数据结构,同时没有必要保存一些测试数据。另一个好处是,当你使用推测模型(inferred model)和 SQLite 存储时,Core Data 可以执行就地(in situ)迁移,严格讲,直接生成并执行 SQL 语句。因为没有载入任何数据,所以此时能保证效率。

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

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

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

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

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

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

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

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

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

      • 将实体/表移出体系 

        注意,不能整合(merge)两个实体体系(if two existing entities do not share a common parent in the source, they cannot share a common parent in the destination) 

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


    定义选项字典,将 NSMigratePersistentStoresAutomaticallyOption 和 NSInferMappingModelAutomaticallyOption 两个键值设置为YES,然后调用 addPersistentStoreWithType:configuration:URL:options:error:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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,这两个方法分别返回源对象和目标对象。

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    - ( 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;
    }


    你可能感兴趣的:(sql,存储,数据存储,ios开发)