custom primary key #639

JanC opened this Issue Jan 5, 2014 · 7 comments


None yet
5 participants

JanC commented Jan 5, 2014

is it possible to use a custom primary key for my MagicalRecord entity? In my case, the primary key is a concatenation of two json attributes and not just one.



casademora commented Jan 5, 2014

That currently isn't possible. We'll keep an eye for this in mr3.0. I have an idea how I can be done.


Sent from my iPad

On Jan 5, 2014, at 11:08 AM, Jan Chaloupecky wrote:

is it possible to use a custom primary key for my MagicalRecord entity? In my case, the primary key is a concatenation of two json attributes and not just one.


Reply to this email directly or view it on GitHub.

@casademora can't this be done by using the import<;attribute;> and manually concatenating the value?

This is definitely an issue I would love to see addressed!
Currently I have to coerce the data from multiple columns into one single artificial primary key field. It comes up a lot for us with the app importing data from multiple hosts with non-unique primary keys between different hosts, we create a composite primary key with host name and the primary key of the object on the server, to make each record unique.
This also very commonly comes up when importing entities that create many to many relationship between other entities. The uniqueness comes from multiple foreign keys not a single primary key.

Alydyn commented Jan 27, 2015

@nacrossweb, as @jostster said you can probably achieve your desired results by implementing import<attribute>

@Alydyn & @jostster I don't think you can. I think what you suggest is fine for any value other than the primary key. If import<attribute> is called on an managed object then it is already to late, as you would have had to fetch that managed object by it's primary key which doesn't exist until after import<attribute>

So you can concatenate multiple values into one, but not use this value as a primary key value.

Further more in 2.2 the managed object is always fetched using the primary keys value from the objectData passed in.
See NSManagedObject+MagicalDataImport
+ (id) MR_importFromObject:(id)objectData inContext:(NSManagedObjectContext *)context;

So if this data doesn't contain your primary key, you are currently out of luck, as far as I understand.

Alydyn commented Feb 3, 2015

First, you should use 2.3beta5 or even better, the develop branch.
Second, per @casademora's article there are a couple of other hooks that you may be able to use more effectively:

  • -shouldImport:
  • -willImport:
  • -didImport:

He doesn't mention this use case but I don't see why you couldn't implement -shouldImport:, examine the data, concatenate the primary key and replace it's entry in data, and then return YES or NO, depending on your success.

Hi @Alydyn thanks for following this up.

Is 2.3beta5 production ready? I checked and the latest official version recorded there is 2.2.
I don't currently have any scope to upgrade for risk of possible compatibility issues, but that is besides the point. I would obviously have a good reason to if this issue was suitably resolved in that version.

shouldImport doesn't seem to be a class method and from the code I am looking at it is actually an instance method called on an already existing object. Which means it is too late to do anything to the data because the object has already been fetched or created as new.

There are two main ways I see this issue being resolved.

  1. Alluded to by your previous responses, would be that we add a class method to preprocess the data before it is imported into each object.

+ (id) preprocessData:(id)dataObject;

Implementing this method and returning a new object could replace the original dataObject used for all subsequent data import calls.

I think this is superior to injecting values back into the original data, which is especially problematic if you are working with some deep immutable structure.

  1. The other option would be to add additional relatedByAttribute keys, when additional relatedByAttribute keys were specified they would be used together when checking if there was already an existing object to update

relatedByAttribute.1 = exampleForiegnKeyA
relatedByAttribute.2 = exampleForiegnKeyB

I think option 1 is probably easier to retrofit in and is perhaps useful in of it self, but option 2 would be a more explicit approach to solving this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment