通常,我们都会尽量使数据模型的变化尽量简单。但有些情况下,不得不进行大的改动,甚至是重新设计数据模型。在这种情况下,之前提过的简单数据迁移已经无法适应了,需要引入Mapping Model这个中间层。



这时,又想起 ​​之前提过​​的一句话:



 



There is no problem  in indirection.



 



这里做一个简单的变动,先为球员增加薪水属性: 



 




Core Data浅谈系列之九 : 使用Mapping Model_Core Data


 


然后创建一名球员,信息如下:


 



Core Data浅谈系列之九 : 使用Mapping Model_数据模型_02


 


这时候我们打算为球员调薪,比如上涨10%。为了结合NSMappingModel,这里简单地增加了一个新的属性newSalary,并且希望在数据迁移时更新该属性。为此,我们创建了一个NSMappingModel映射模型:


 



Core Data浅谈系列之九 : 使用Mapping Model_Core Data_03


 



Core Data浅谈系列之九 : 使用Mapping Model_数据迁移_04


 



Core Data浅谈系列之九 : 使用Mapping Model_Core Data_05


 


选择好源数据模型和目标数据模型,设置newSalary和salary的关系:


 



Core Data浅谈系列之九 : 使用Mapping Model_Core Data_06


 


这表示目标属性newSalary的值为源属性salary的1.1倍。


 


这个时候,我们不希望Core Data自动为我们映射模型,所以修改一下迁移选项: 


[cpp]  ​​view plain​​ ​​copy​​


  1. NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:  
  2. [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,  
  3. [NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption, nil];  


[cpp]  ​​view plain​​ ​​copy​​


  1. NSString *mappingModelPath = [[NSBundle mainBundle] pathForResource:@"mappingModel3to4" ofType:@"cdm"];  
  2. NSURL *mappingModelUrl = [NSURL fileURLWithPath:mappingModelPath];  
  3. NSMappingModel *mappingModel = [[[NSMappingModel alloc] initWithContentsOfURL:mappingModelUrl] autorelease];  


[cpp]  ​​view plain​​ ​​copy​​


  1. NSMigrationManager *migrationManager = [[[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel] autorelease];  
  2.   
  3. if (![migrationManager migrateStoreFromURL:storeURL type:NSSQLiteStoreType options:nil withMappingModel:mappingModel  toDestinationURL:tmpStoreURL destinationType:NSSQLiteStoreType destinationOptions:nil error:&error]) {  
  4. "Error migrating %@, %@", error, [error userInfo]);  
  5.     abort();  
  6. }  
  7.   
  8. NSFileManager *fileManager = [NSFileManager defaultManager];  
  9. NSString *oldStoreName = @"cdNBA_old.sqlite";  
  10. NSURL *oldStoreURL = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:oldStoreName]];  
  11. [fileManager moveItemAtURL:storeURL toURL:oldStoreURL error:&error];  
  12. [fileManager moveItemAtURL:tmpStoreURL toURL:storeURL error:&error];  


Core Data浅谈系列之九 : 使用Mapping Model_数据迁移_07


可以发现有一份旧的sqlite文件和一份新的。


通过查看新的sqlite文件中的数据,可以得知newSalary的值: 



Core Data浅谈系列之九 : 使用Mapping Model_Core Data_08


 


其中,newSalary为2420000.0,刚好是salary的值2200000.0的1.1倍。