Reputation: 3652
I'm trying to manually invoke a CoreData migration using data models created by xcode (.xcdatamodel) and a mapping model created programmatically, at run-time. The migration appears to finish with no errors but the newly created database has no data in it. The structure of the DB is there (tables, Z_METADATA, etc) but the data has not carried over and apparently my NSMappingModel is not being applied.
To summarize the migration: Country entity has been renamed to Country2 and Country.name has been renamed to Country2.new_name.
NSMutableArray *attrMaps = [[NSMutableArray alloc] init];
NSPropertyMapping *pMap = [[NSPropertyMapping alloc] init];
pMap.name = @"new_name";
pMap.valueExpression = [NSExpression expressionForKeyPath:@"source.name"];
[attrMaps addObject:pMap];
NSEntityMapping *eMap = [[NSEntityMapping alloc] init];
eMap.sourceEntityName = @"Country";
eMap.destinationEntityName = @"Country2";
eMap.name = @"CountryToCountry2";
eMap.mappingType = NSTransformEntityMappingType;
eMap.attributeMappings = attrMaps;
NSMutableArray *eMaps = [[NSMutableArray alloc] init];
[eMaps addObject:eMap];
NSMappingModel *mappingModel = [[NSMappingModel alloc] init];
mappingModel.entityMappings = eMaps;
NSURL * storeURL = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@/Documents/%@",NSHomeDirectory(),@"TestCoreData.sqlite"]];
NSURL * storeURL2 = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@/Documents/%@",NSHomeDirectory(),@"TestCoreData2.sqlite"]];
NSMigrationManager *migman = [self getMigrationManager];
NSError * err;
BOOL ok = [migman migrateStoreFromURL:storeURL
type:NSSQLiteStoreType
options:nil
withMappingModel:mappingModel
toDestinationURL:storeURL2
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&err];
More Info
Comparing my hand-made NSMappingModel to one created in XCode's GUI, you can see a few differences:
From Xcode's GUI
entityMappings (
"(NSEntityMapping),
name CountryToCountry2,
mappingType 5,
sourceEntityName Country,
sourceEntityVersionHash <828c33cf 3ffdc5df dd1e73e8 4f7b60a5 f10dcb43 af26adeb 33d2c518 0c992dd8>,
destinationEntityName Country2,
destinationEntityVersionHash <8cdb8ecf cb47b39d 4b45858f a247487a dd88088b f509a6ec cc938740 5cf7a041>, attributeMappings (
"(NSPropertyMapping), name new_name, valueExpression $source.name, userInfo (null)"
), relationshipMappings (
), sourceExpression FETCH(FUNCTION($manager, "fetchRequestForSourceEntityNamed:predicateString:" , "Country", "TRUEPREDICATE"), $manager.sourceContext, NO),
entityMigrationPolicyClassName (null), userInfo (null)"
Mine
entityMappings (
"(NSEntityMapping),
name CountryToCountry2,
mappingType 5,
sourceEntityName Country,
sourceEntityVersionHash (null),
destinationEntityName Country2,
destinationEntityVersionHash (null),
attributeMappings (
"(NSPropertyMapping), name new_name, valueExpression source.name, userInfo (null)",
), relationshipMappings (
), sourceExpression (null),
entityMigrationPolicyClassName (null), userInfo (null)"
Update
I've added this sourceExpression to my Entity mapping and now the rows of Country are copied over to the new DB but they are empty. So still seems the NSPropertyMappings are not taking effect:
eMap.sourceExpression = [NSExpression expressionWithFormat:@"FETCH(FUNCTION($manager, \"fetchRequestForSourceEntityNamed:predicateString:\" , \"Country\", \"TRUEPREDICATE\"), $manager.sourceContext, NO)"];
Upvotes: 0
Views: 552
Reputation: 3652
The valueExpression for the NSPropertyMapping was defined incorrectly. It should be expressionWithFormat:
not expressionForKeyPath:
and $source
not source
. Like this:
pMap.valueExpression = [NSExpression expressionWithFormat:@"$source.name"];
And with that, I have a hand-made NSMappingModel actually working.
Upvotes: 1