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.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment