Showing posts with label magicalrecord. Show all posts
Showing posts with label magicalrecord. Show all posts

Monday, June 19, 2017

How to purge an entity and after add new records with magical record

Leave a Comment

When I request new data I want to delete all the records before adding news. Sometimes there is no changes between the old datas recorded and the new datas.

This is what I tried but my new record are never saved (always 0 records saved)

When I request data:

Autorisation* aut = [Autorisation MR_createEntity]; // setter method 

When I want to save:

+(void)saveAutorisationList:(NSMutableArray*)autorisationList{     NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext];     for (Autorisation* aut in [self getAutorisationList]) {       [aut MR_deleteEntityInContext:localContext];  // method that return all Autorisation     }     [localContext MR_saveToPersistentStoreWithCompletion:^(BOOL contextDidSave, NSError * error) {         for (Autorisation* aut in autorisationList) {             [aut MR_inContext:localContext];         }         [localContext MR_saveToPersistentStoreWithCompletion:nil];     }]; }  +(NSMutableArray*)getAutorisationList {     NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext];     return [[Autorisation MR_findAllInContext:localContext] mutableCopy]; } 

1 Answers

Answers 1

What is going on here is that you're deleting all objects, including those which you want to save. Here is step by step what's going on:

+(void)saveAutorisationList:(NSMutableArray*)autorisationList {     // as it seems, here autorisationList is a list of new objects you want to save.      NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext]; 

Wrong behavior starts here:

    for (Autorisation* aut in [self getAutorisationList]) { 

Here getAutorisationList fetched all objects, currently existing in localContext, old + new ones.

      [aut MR_deleteEntityInContext:localContext];         // here you deleted each Autorisation object currently existing, including those you want to save     }     ... } 

Instead, you should find diffs between what you received and what existed before, and delete only those objects which were not received with the update.

E.g. imagine you had set of objects OldSet = {auth1, auth2, auth3}, and with update you received objects NewSet = {auth2, auth3, auth4}. Diffs for deletion would be

ToBeDeletedSet = OldSet - NewSet = {auth1} 

In this way you will keep the records which you had, and save new records as well.

Then, your save method will look like this:

+(void)saveAutorisationList:(NSMutableArray*)updatedAutorisationList{     NSManagedObjectContext* localContext = [NSManagedObjectContext MR_defaultContext];     NSMutableArray *oldAutorisationList = [self getAutorisationList];     [oldAutorisationList removeObjectsInArray: updatedAutorisationList];     for (Autorisation* aut in oldAutorisationList) {       [aut MR_deleteEntityInContext:localContext];  // method that return all Autorisation     }     [localContext MR_saveToPersistentStoreWithCompletion:^(BOOL contextDidSave, NSError * error) {         for (Autorisation* aut in autorisationList) {             [aut MR_inContext:localContext];         }         [localContext MR_saveToPersistentStoreWithCompletion:nil];     }]; } 
Read More

Thursday, April 14, 2016

Need Help Diagnosing NSMergeConflict Error

Leave a Comment

I've been struggling to resolve an NSMergeConflict in an app I am working on. I know I could just change the merge policy, but I'm concerned about possibly corrupting the data since I don't know exactly which of the conflicting objects is correct and which is out of date. To make things even more complicated, the merge conflict is not actually in the object I am modifying and saving. Instead it appears to be coming from some related objects that I am not directly modifying.

The relationship graph looks something like this:

Order <<-----> Customer  Order <<-----> Rep  Rep   <<-----> Customer 

where Order is the object I am modifying and saving and Customer and Rep are the objects that the merge error is complaining about.

What I really can't figure out is how to debug this issue and track down where my data is getting out of sync. Does anyone know of a good way to get more data about what is going on in my code? Is there a way to log what is in all the persistence contexts and see where they are diverging?

Update: I changed the relationship between Order and Rep such that Rep no longer has a collection of Orders and that solved some of the issues. Unfortunately, that solution is not an option for the relationship between Order and Customer and I am still seeing errors there.

Here is a sample stacktrace of the error I am getting:

NSMergeConflict (0x1465972e0) for NSManagedObject (0x1462147a0) with objectID '0xd000000000a00008 <x-coredata://1F648314-CA44-4DA5-B437-07BFCB96D1E9/Customer/p40>' with oldVersion = 13 and newVersion = 14 and old object snapshot = { address = "{\n    cmpnts =     (\n                {\n            \"long_name\" = \"2318 W 5TH AVE\";\n            \"short_name\" = \"2318 W 5TH AVE\";\n            types =             (\n                \"street_address\"\n            );\n        },\n                {\n            \"long_name\" = GARY;\n            \"short_name\" = GARY;\n            types =             (\n                locality\n            );\n        },\n                {\n            \"long_name\" = IN;\n            \"short_name\" = IN;\n            types =             (\n                \"administrative_area_level_1\"\n            );\n        },\n                {\n            \"long_name\" = \"Lake County\";\n            \"short_name\" = \"Lake County\";\n            types =             (\n                \"administrative_area_level_2\"\n            );\n        },\n                {\n            \"long_name\" = \"46404-1331\";\n            \"short_name\" = \"46404-1331\";\n            types =             (\n                \"postal_code\"\n            );\n        }\n    );\n    lat = \"41.60221\";\n    lng = \"-87.366285\";\n    loc = \"2318 W 5TH AVE, GARY, IN, 46404-1331\";\n}"; buyingGroup = "<null>"; compositeName = "20/20 EYE SPECIALIST (#385468)"; created = "2014-10-29 19:36:43 +0000"; "created_by_id" = 5451215fe4b007ffb46431bf; "current_due" = 0; customer = 385468; customerTotal = "0xd0000000db74000a <x-coredata://1F648314-CA44-4DA5-B437-07BFCB96D1E9/CustomerTotals/p14045>"; detail = "0xd00000000504000c <x-coredata://1F648314-CA44-4DA5-B437-07BFCB96D1E9/CustomerDetail/p321>"; "device_address_section_key" = 2; "device_address_sort_key" = "2318 W 5TH AVE"; "device_city_section_key" = G; "device_city_sort_key" = GARY; "device_corp_ytd_gross" = 0; "device_created_section_key" = "01/01/1980"; "device_customer_section_key" = 3; "device_deleted" = 0; "device_exported" = "<null>"; "device_last_view" = "2016-04-12 17:04:51 +0000"; "device_latitude" = "41.60221"; "device_loaded" = "2016-04-12 15:25:07 +0000"; "device_longitude" = "-87.366285"; "device_name_section_key" = 2; "device_note_date" = "<null>"; "device_note_text" = "<null>"; "device_phone_section_key" = 2; "device_phone_sort_key" = 2198850116; "device_rolling_12_credits" = 0; "device_rolling_12_net" = 0; "device_rolling_12_rd" = 0; "device_rolling_12_rx" = 0; "device_state_section_key" = I; "device_state_sort_key" = IN; "device_updated" = "<null>"; "device_ytd_credits" = 0; "device_ytd_gross" = 0; "device_ytd_net" = 0; "device_ytd_rd" = 0; "device_ytd_rx" = 0; "device_zip_section_key" = 4; "device_zip_sort_key" = "46404-1331"; "dw_fax" = ""; "dw_open_date" = "1980-01-01 05:00:00 +0000"; "is_inherited" = 0; jobsonCensus = "0xd000000001a4000e <x-coredata://1F648314-CA44-4DA5-B437-07BFCB96D1E9/JobsonCensus/p105>"; "jobson_census_id" = 5494225284aec464730b3aa1; "last_order_date" = "<null>"; "last_sync" = "2016-04-12 15:58:20 +0000"; name = "20/20 EYE SPECIALIST"; primaryContact = "<null>"; "remote_id" = 545141cbe4b024c7a6033055; "updated_at" = "2015-09-15 11:48:11 +0000"; "updated_by_id" = "<null>"; } and new cached row = {     address = "{\n    cmpnts =     (\n                {\n            \"long_name\" = \"2318 W 5TH AVE\";\n            \"short_name\" = \"2318 W 5TH AVE\";\n            types =             (\n                \"street_address\"\n            );\n        },\n                {\n            \"long_name\" = GARY;\n            \"short_name\" = GARY;\n            types =             (\n                locality\n            );\n        },\n                {\n            \"long_name\" = IN;\n            \"short_name\" = IN;\n            types =             (\n                \"administrative_area_level_1\"\n            );\n        },\n                {\n            \"long_name\" = \"Lake County\";\n            \"short_name\" = \"Lake County\";\n            types =             (\n                \"administrative_area_level_2\"\n            );\n        },\n                {\n            \"long_name\" = \"46404-1331\";\n            \"short_name\" = \"46404-1331\";\n            types =             (\n                \"postal_code\"\n            );\n        }\n    );\n    lat = \"41.60221\";\n    lng = \"-87.366285\";\n    loc = \"2318 W 5TH AVE, GARY, IN, 46404-1331\";\n}";     buyingGroup = "<null>";     compositeName = "20/20 EYE SPECIALIST (#385468)";     created = "2014-10-29 19:36:43 +0000";     "created_by_id" = 5451215fe4b007ffb46431bf;     "current_due" = 0;     customer = 385468;     customerTotal = "0xd0000000db74000a <x-coredata://1F648314-CA44-4DA5-B437-07BFCB96D1E9/CustomerTotals/p14045>";     detail = "0xd00000000504000c <x-coredata://1F648314-CA44-4DA5-B437-07BFCB96D1E9/CustomerDetail/p321>";     "device_address_section_key" = 2;     "device_address_sort_key" = "2318 W 5TH AVE";     "device_city_section_key" = G;     "device_city_sort_key" = GARY;     "device_corp_ytd_gross" = 0;     "device_created_section_key" = "01/01/1980";     "device_customer_section_key" = 3;     "device_deleted" = 0;     "device_exported" = "<null>";     "device_last_view" = "2016-04-12 17:04:51 +0000";     "device_latitude" = "41.60221";     "device_loaded" = "2016-04-12 15:25:07 +0000";     "device_longitude" = "-87.366285";     "device_name_section_key" = 2;     "device_note_date" = "<null>";     "device_note_text" = "<null>";     "device_phone_section_key" = 2;     "device_phone_sort_key" = 2198850116;     "device_rolling_12_credits" = 0;     "device_rolling_12_net" = 0;     "device_rolling_12_rd" = 0;     "device_rolling_12_rx" = 0;     "device_state_section_key" = I;     "device_state_sort_key" = IN;     "device_updated" = "<null>";     "device_ytd_credits" = 0;     "device_ytd_gross" = 0;     "device_ytd_net" = 0;     "device_ytd_rd" = 0;     "device_ytd_rx" = 0;     "device_zip_section_key" = 4;     "device_zip_sort_key" = "46404-1331";     "dw_fax" = "";     "dw_open_date" = "1980-01-01 05:00:00 +0000";     "is_inherited" = 0;     jobsonCensus = "0xd000000001a4000e <x-coredata://1F648314-CA44-4DA5-B437-07BFCB96D1E9/JobsonCensus/p105>";     "jobson_census_id" = 5494225284aec464730b3aa1;     "last_order_date" = "<null>";     "last_sync" = "2016-04-12 16:06:52 +0000";     name = "20/20 EYE SPECIALIST";     primaryContact = "<null>";     "remote_id" = 545141cbe4b024c7a6033055;     "updated_at" = "2015-09-15 11:48:11 +0000";     "updated_by_id" = "<null>"; } 

1 Answers

Answers 1

It seems to my that the relationship from Customer to Rep is redundant, unless it is completely unrelated to the Order entity. If Reps are linked to Customers only via the Orders, you could get the Reps for a customer like this:

Set(arrayLiteral: customer.orders.map { $0.rep }) 

As for logging more debug output you could switch on sql debugging, although you would have to extrapolate what Core Data is doing. (Add -com.apple.CoreData.SQLDebug 1 to the Run Scheme.)

If updating orders affects your Users or Reps you could check if you have some delete rule with unintended consequences.

Read More