问题
EDIT 1 While I understand that for this particular scenario (and other alike) I could use the mapping editor alone to migrate my store correctly so that the values in the persistent store don't jump around, but that's not a solution to my current problem but only avoids addressing the root of the problem. I am keen on sticking with my custom migration policy as this will give me a lot of control through the migration process, especially for future scenarious where setting up a custom migration policy will work for me. This is for a long term solution and not just for this scenario.
I urge you to try and help me solve the current situation at hand rather than diverting me to lightweight migration or advising me to avoid using a migration policy. Thank you.
I really do look forward to sorting this out and your valuable input/ideas on what I could do to fix this problem.
What I have done:
I have a migration policy set up so that the source data can be copied into the destination data from version 1 of the core model to version 2.
This is the migration policy:
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error {
// Create the product managed object
NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
inManagedObjectContext:[manager destinationContext]];
NSString *productCode = [sInstance valueForKey:@"productCode"];
NSNumber *productPrice = [sInstance valueForKey:@"productPrice"];
[newObject setValue:productCode forKey:@"productCode"];
[newObject setValue:productPrice forKey:@"productPrice"];
//This is the field where the name has changed as well as the type.
[newObject setValue:[NSNumber numberWithBool:YES] forKey:@"productPriceNeedsUpdating"];
// Set up the association between the old source product and the new destination Product for the migration manager
[manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];
/*
A test statement to make sure the destination object contains the correct
values int he right properties:
Product description: <NSManagedObject: 0xb983780> (entity: Product; id: 0xb9837b0 <x-coredata:///Product/t97685A9D-09B4-475F-BDE3-BC9176454AEF6> ; data: {
productCode = 9999;
productPrice = "2.09";
productPriceNeedsUpdating = 1;
})
*/
// Set up the association between the old source product and the new destination Product for the migration manager
return YES;
}
So even though the tested properties show the correct values in runtime, the resultant values saved in the data model store is incorrect as seen in the snapshots.
Here is a comparison from version 1 to version 2 of the data store.
Version 1: Correct
to Version 2: Which is now storing the values incorrectly.
The expected output should have the Product price inserted into the productPrice field and not in the ProductPriceNeedsUpdating field which should actually only have boolean values.
Can anyone help me understand what I am doing wrong, or explain whats happening here?
UPDATE 1 - Here are my entity mappings:
Update 2 - 20/aug/2014 01:02 GMT
When I remove the attribute ProductPriceLastUpdated of type date from version 1, and remove the attribute ProductPriceNeedsUpdate of type boolean in version 2, leaving only the two attributes that both match in version 1 and 2, then everything works. Even though I can leave it here and move on, I cant ignore the users that are currently using version 1 of the database which does have that pointless ProductPriceLastUpdated attribute which I need the type converted to boolean and also have the name changed to ProductPriceNeedsUpdate. Thats when things start going weird, and the price values are shown in the ProductPriceNeedsUpdate field instead of the productPrice field.
I hope someone can address the original problem and tell me why it is that the entityMapping, or more so, property mapping is not being saved properly?
Update 3 - EntityMapping and properties:
Version 1
Version 2
Any ideas?
回答1:
First, if you want to just use a lightweight migration (which you really should in this case) you can get rid of your custom migration policy. In this instance, it's not needed. And, as a matter of fact, you can get rid of your custom mapping model as well. All you need to do is in your Version 2 model, select the productPriceNeedsUpdating boolean flag, and in the Attribute Detail inspector on the right, set the default value to YES. This will achieve the goal you're try to get to with your custom migration policy.
However, if you really need to write this in code with your custom migration policy, I would still not use custom code. You can achieve this migration with only a mapping model. Simply select the ProductToProduct mapping, and in the value expression for productNeedsUpdating, enter YES, or 1.
EDIT
So, after a rather lengthy screen share, it was determined that the migration was using code from Marcus Zarra's Core Data book describing progressively migrating stores. When this was written, WAL mode was not the default mode with Core Data. When WAL mode is enabled, progressively migrating stores don't function well since there are two more files to deal with, the Write Ahead Log, and the Shared Memory file. When simply replacing the old store with a new one, without first removing those files, odd things happen, such as described in this post. The solution ultimately ended up being to disable WAL mode for the progressively migrating scenario so the extra files are not generated in the first place.
来源:https://stackoverflow.com/questions/25354211/property-mapping-not-being-associated-correctly-why