property mapping not being associated correctly. Why?
Asked Answered
S

1

4

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 enter image description here

to Version 2: Which is now storing the values incorrectly.

Wrong values being saved into the database in the wrong fields

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:

enter code here

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 enter image description here

Version 2 enter image description here

Any ideas?

Sylvestersylvia answered 17/8, 2014 at 22:22 Comment(3)
Did you try lightweight migration? I didn't watch whole video yet, but at first glance your changes might fit. (For Core Data to be able to generate an inferred mapping model, changes must fit an obvious migration pattern, for example:Simple addition of a new attribute Removal of an attribute)Ojeda
It would be helpful to fellow users here if you could try to describe your problem in more detail here, rather than linking off to a video on Dropbox.Multiparous
@TimurKuchkarov lightweight migration would not suit my needs, since I would be doing more changes to the core data model. I needed to know how to have xcode read the mapping model and update the persistent store to the latest model. I believe the process is called progressive migration.Sylvestersylvia
A
5

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.

Aara answered 20/8, 2014 at 1:56 Comment(13)
Hi, Thank you for posting. I believe you have missed the note that came along with the bounty. I am not looking to do a light migration as in the future I will be doing a lot of heavy migrations. Think whatsapp for example after a new feature update, and huge store model changes through each revision. This is only a trivial example that I'm doing just to get warmed up for when I do need to do custom heavy migrations. If you could understand the question I have written and then write a response in relation to the problem and how I could have it solved, then that would be most appreciated!Sylvestersylvia
Its bloody annoying that I can't figure out whats causing the values to be in the wrong field. I understand why you say that light migration can be used in this case - however I really do wish to get my hands dirty with custom heavy migration and already have it all working beautifully with the only exception that I dont understand why the values are being inserted into the WRONG field/column, and why the other column is showing nill. The boolean field should have yes, and the price shold have the price values. The product codes are correct in this case - being a 4 digit number.Sylvestersylvia
Any ideas casademora?Sylvestersylvia
Have you looked at your mapping model and double checked that you didn't cross fields there somehow? Why not try setting aside your current mapping model, and try it againt from step 1. I need to do this sometimes when I've made a simple mistake and I cant find it. No need to delete your current model, just remove it from the build target, and start freshAara
how do you do that? And wouldnt that change the hash tags of the core data model for revision 1 therefor not being able to transition smoothly or is that not the case? The goal is to make sure that the current version 1 within the app can be migrated to version 2 (which I am able to do) with the exception of the values being in the wrong field.. I have cross checked it all!Sylvestersylvia
Can we perhaps enter into a live discussion so that we can eliminate this problem once and for all with the added benefit of you being able to see my screen live?Sylvestersylvia
Only if we can screen capture our session and make it public by linking to it here, as well as other places on the interwebs.Aara
casademora, I'm not sure if there was a hint of sarcasm.. I assure you that the intention isn't to create a screencapture. I'm not interested in seeing your face, but ONLY for you to be able to see my screen. I am available right now for a session, this problem really is busting my balls, and I'm afraid that if I continue to bust any longer that they would crack ceasing the ability to have kids in the future, and I WANT THEM! Care to lend your eyes?Sylvestersylvia
Normally, I charge my consulting rate for a request like this. Since this is stack overflow, I want to record it for later distribution to help other people who have the same problem.Aara
Ok great. I can do that for you and pass you the file. I have the screencast session 1080p if not higher setup ready for the session. Shall we get it rolling now?Sylvestersylvia
Let us continue this discussion in chat.Sylvestersylvia
Yes I can make a screen cast of our session and link it to this post. It will be in 1080p quality. Could you pop into chat please? I've just been waiting around hoping for you to come into the chat only to realise you might have accidentally missed it 15 minutes ago!Sylvestersylvia
You, my friend, have a great positive attitude. I loved the approach. It was a fun and informative screen share! I appreciate the sound advice and will most definitely be attending the next NSLondon meetup event. See you in the future, mate. Pavan - the WAL guy ;)Sylvestersylvia

© 2022 - 2024 — McMap. All rights reserved.