Core Data Primary Key

54,271

Solution 1

Your options are:

  • Use -[NSManagedObject objectID]. Note that this ID is temporary until either the object is saved for the first time or you call -[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
  • Use the CFUUID family of functions to generate a UUID for each object in your -awakeFromInsert method
  • Create your own primary key-like system that stores an integer in your model and increments it with the creation of each object

There is no good way to validate that a property is unique. The closest you'll get is to ensure it is unique at creation time, and then implement a custom setter method that stops anyone ever changing the ID.

Solution 2

Keep in mind that Core Data is an object-graph persistence framework, not a database. Things like primary keys are abstracted away because they depend on the implementation of the persistent store.

Solution 3

Core Data makes its own primary key - you don't have to add one. You can retrieve it with

NSManagedObjectID *moID = [managedObject objectID];

Solution 4

sometimes when hacking one needs the actual int of the primary key. here is how one can grab it:

NSManagedObjectID *yourManagedObjectID = [yourManagedObject objectID];
int yourManagedObject_PK = [[[[[yourManagedObjectID URIRepresentation] absoluteString] lastPathComponent] substringFromIndex:1] intValue];

despite CoreData being an object graph, if one looks at the CoreData generated SQLite database data, this way of grabbing the primary key of an NSManagedObject should not be a problem. ii have used CoreData and the low level sqlite3 C library together in the same code and passing primary keys from CoreData to sqlite3 for fetching records works just fine.

! if You intend to use this code in production, be aware of possible internal changes to the way the db primary key transforms into a URIRepresentation, it might brake Your code.

enjoy

Share:
54,271

Related videos on Youtube

Mugunth
Author by

Mugunth

iOS Developer/Author/Blogger and Usability Guy. http://blog.mugunthkumar.com Co-author of the book iOS Programming: Pushing the Limits I will not answer your question here on Stackoverflow if you ask anything about Iphone or IPHONE or I-phone.

Updated on July 05, 2022

Comments

  • Mugunth
    Mugunth almost 2 years

    This may seem stupid, but I still couldn't figure out how to mark a attribute as a primary key in the xcdatamodel file. My persistent storage is sqlite file. Can anyone help me?

    In that case, how can I "validate" a ID to be unique? Should I write a validation method or something?

  • Konstantin
    Konstantin almost 13 years
    A much more constructive answer - you should be marked as the solution!
  • eonil
    eonil over 11 years
    No relation is defined between object-ID and SQLite RID. Could be usable for temporary key only for specific version, but wrong approach for persistent Primary Key because it can be broken at other version silently.
  • manitu
    manitu over 11 years
    what exactly did You mean by "broken at other version"? why should primary keys change?
  • eonil
    eonil over 11 years
    PK values won't be changed, but algorithm which makes URL representation may be changed, because no algorithm is defined officially. And in that case your code is not guaranteed to extract valid PK value. (if you have any source defines the algorithm, let me know, then I will recommend you posting)
  • manitu
    manitu over 11 years
    Eonil, you may have noticed ii wrote "sometimes when hacking", ii think the algorithm won't change, at least not in a way that would kill my db access. primary key uniquely marks some piece of data, it just needs to stay the same as long as that data is there. the URI representation may change, but not the PK. there is millions of such databases out there, already baked and in the end, it is a very simple algorithm, it always puts the actual SQLite INTEGER primary key at the end of the string. Example URI absolute string: "x-coredata://DB12B6A9-E6F4-40A9-B6DB-51AE185DBD39/Waltype/p‌​1".
  • eonil
    eonil over 11 years
    OK. sometimes when hacking part is convincible. My down-vote is currently locked-in, so you make some edit I will remove the down-vote.
  • eonil
    eonil over 11 years
    Anyway the assumption that algorithm won't be changed is just only your opinion which is not defined anywhere. And you are not the API author. Apple is famous for their legacy ignorance. If they need it, they will do it. Apple's stance has been always update your app. They sometimes do this even on official API (though with announcement), and this is not even official. It's very likely to happen silently. In that case, your algorithm will make some unpredictable value which may break data integrity based on the result.
  • manitu
    manitu over 11 years
    You are completely right about Apple and ii am aware of the danger. thanks!
  • object2.0
    object2.0 almost 11 years
    Generating UUID is best way to go. We are using it in our app and it is serving very well.
  • Leonard
    Leonard over 10 years
    This should've been the answer the answer @Mugunth should've chosen! Thank you for your insight.
  • Eric Giguere
    Eric Giguere over 9 years
    For sake of speed and effectiveness, sql is sometimes the way to go. My exemple, a query holding count(*), sums, averages and groups. Its a PAIN to do in OO, single line for sql! That 'hack' works perfectly and if Apple change it, well they will have to still make the sql join work in some way, so I guess we are ok for a while ;). Vote UP even if theoretically we shouldn't do this. Hiding completely the DB is, in my opinion, an error more driven by principles than real technical reasons. We do that, get batches by SQL. all the time in many other systems even though a framework is available.
  • fat32
    fat32 over 8 years
    Not really recommended, when can you guarantee that not more than one object is created at the same time?
  • Cody
    Cody almost 8 years
    Not recommended too . This method can't guarantee the key is unique.
  • infiniteLoop
    infiniteLoop almost 8 years
    @Fynh I dint posted the code and ya my post may in incomplete though, I am always sync'ing the time getter method.
  • M. Ryan
    M. Ryan almost 7 years
    this is a dangerous suggestion. if you have a software design problem that requires a unique integer key you are WAY better off just creating one in CoreData as part of your model manually than trying to hack this out by substringing the GUID that CoreData creates. This is NOT a durable and reliable solution.
  • manitu
    manitu almost 7 years
    it is pretty durable actually, still working since 2012 in the foodnmood.org app... have not updated a single bit since then! not sure how else one would be able to deal with low level sqlite3, without a proper int... :) @M.Ryan what do You mean by: creating integer key in CoreData, do You have an example or just thinking out loud?
  • Next Developer
    Next Developer over 6 years
    so will Core Data just generate the primary key on its own?