Core Data浅谈系列之九 : 使用Mapping Model
2014-05-06 18:11
169 查看
原帖地址:http://blog.csdn.net/jasonblog/article/details/8528755
通常,我们都会尽量使数据模型的变化尽量简单。但有些情况下,不得不进行大的改动,甚至是重新设计数据模型。在这种情况下,之前提过的简单数据迁移已经无法适应了,需要引入Mapping Model这个中间层。
这时,又想起之前提过的一句话:
There is no problem in computer science that can’t be solved by adding another
level of indirection.
这里做一个简单的变动,先为球员增加薪水属性:
然后创建一名球员,信息如下:
这时候我们打算为球员调薪,比如上涨10%。为了结合NSMappingModel,这里简单地增加了一个新的属性newSalary,并且希望在数据迁移时更新该属性。为此,我们创建了一个NSMappingModel映射模型:
选择好源数据模型和目标数据模型,设置newSalary和salary的关系:
这表示目标属性newSalary的值为源属性salary的1.1倍。
这个时候,我们不希望Core Data自动为我们映射模型,所以修改一下迁移选项:
[cpp] view
plaincopy
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption, nil];
把NSInferMappingModelAutomaticallyOption设置为NO后,我们需要手工指定映射模型:
[cpp] view
plaincopy
NSString *mappingModelPath = [[NSBundle mainBundle] pathForResource:@"mappingModel3to4" ofType:@"cdm"];
NSURL *mappingModelUrl = [NSURL fileURLWithPath:mappingModelPath];
NSMappingModel *mappingModel = [[[NSMappingModel alloc] initWithContentsOfURL:mappingModelUrl] autorelease];
接着,进行实质性的数据迁移。简单起见,这里就没有做错误检查了:
[cpp] view
plaincopy
NSMigrationManager *migrationManager = [[[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel] autorelease];
if (![migrationManager migrateStoreFromURL:storeURL type:NSSQLiteStoreType options:nil withMappingModel:mappingModel toDestinationURL:tmpStoreURL destinationType:NSSQLiteStoreType destinationOptions:nil error:&error]) {
NSLog(@"Error migrating %@, %@", error, [error userInfo]);
abort();
}
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *oldStoreName = @"cdNBA_old.sqlite";
NSURL *oldStoreURL = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:oldStoreName]];
[fileManager moveItemAtURL:storeURL toURL:oldStoreURL error:&error];
[fileManager moveItemAtURL:tmpStoreURL toURL:storeURL error:&error];
再跑一遍Demo,然后在终端里查看:
可以发现有一份旧的sqlite文件和一份新的。
通过查看新的sqlite文件中的数据,可以得知newSalary的值:
其中,newSalary为2420000.0,刚好是salary的值2200000.0的1.1倍。
通常,我们都会尽量使数据模型的变化尽量简单。但有些情况下,不得不进行大的改动,甚至是重新设计数据模型。在这种情况下,之前提过的简单数据迁移已经无法适应了,需要引入Mapping Model这个中间层。
这时,又想起之前提过的一句话:
There is no problem in computer science that can’t be solved by adding another
level of indirection.
这里做一个简单的变动,先为球员增加薪水属性:
然后创建一名球员,信息如下:
这时候我们打算为球员调薪,比如上涨10%。为了结合NSMappingModel,这里简单地增加了一个新的属性newSalary,并且希望在数据迁移时更新该属性。为此,我们创建了一个NSMappingModel映射模型:
选择好源数据模型和目标数据模型,设置newSalary和salary的关系:
这表示目标属性newSalary的值为源属性salary的1.1倍。
这个时候,我们不希望Core Data自动为我们映射模型,所以修改一下迁移选项:
[cpp] view
plaincopy
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption, nil];
把NSInferMappingModelAutomaticallyOption设置为NO后,我们需要手工指定映射模型:
[cpp] view
plaincopy
NSString *mappingModelPath = [[NSBundle mainBundle] pathForResource:@"mappingModel3to4" ofType:@"cdm"];
NSURL *mappingModelUrl = [NSURL fileURLWithPath:mappingModelPath];
NSMappingModel *mappingModel = [[[NSMappingModel alloc] initWithContentsOfURL:mappingModelUrl] autorelease];
接着,进行实质性的数据迁移。简单起见,这里就没有做错误检查了:
[cpp] view
plaincopy
NSMigrationManager *migrationManager = [[[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel] autorelease];
if (![migrationManager migrateStoreFromURL:storeURL type:NSSQLiteStoreType options:nil withMappingModel:mappingModel toDestinationURL:tmpStoreURL destinationType:NSSQLiteStoreType destinationOptions:nil error:&error]) {
NSLog(@"Error migrating %@, %@", error, [error userInfo]);
abort();
}
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *oldStoreName = @"cdNBA_old.sqlite";
NSURL *oldStoreURL = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:oldStoreName]];
[fileManager moveItemAtURL:storeURL toURL:oldStoreURL error:&error];
[fileManager moveItemAtURL:tmpStoreURL toURL:storeURL error:&error];
再跑一遍Demo,然后在终端里查看:
可以发现有一份旧的sqlite文件和一份新的。
通过查看新的sqlite文件中的数据,可以得知newSalary的值:
其中,newSalary为2420000.0,刚好是salary的值2200000.0的1.1倍。
相关文章推荐
- Core Data浅谈系列之九 : 使用Mapping Model
- Core Data浅谈系列之九 : 使用Mapping Model
- Core Data浅谈系列之九 : 使用Mapping Model
- Core Data浅谈系列之七 : 使用NSFetchedResultsController
- Core Data浅谈系列之七 : 使用NSFetchedResultsController
- Core Data浅谈系列之七 : 使用NSFetchedResultsController
- Core Data浅谈系列之七 : 使用NSFetchedResultsController
- Core Data浅谈系列之七 : 使用NSFetchedResultsController
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十五)地图编辑器的初步使用
- debian/ubuntu server学习整理系列之一:基本日常使用与软件包管理
- Ansible Tower系列 三(使用tower执行一个任务)【转】
- Maven 系列 一 :Maven 快速入门及简单使用【转】
- 使用Gradle构建SpringBoot工程系列:第二篇:开发环境准备
- 使用lua写gui程序系列汇总
- 数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量
- 泛型系列<4>使用相应的泛型版本替换Stack和Queue
- Java 集合系列08之 List总结(LinkedList, ArrayList等使用场景和性能分析)
- 【Silverlight】Bing Maps学习系列(六):使用扩展模式(Extended Modes)
- Maven提高篇系列之四——使用Profile
- Yii框架官方指南系列24——使用数据库:Query Builder