How to (properly) create unique object IDs for instances of NSManagedObject? - objective-c

I want to set custom NSManagedObject IDs to match the IDs of their corresponding objects in my CouchDB. The CoreData documentation (in "Using Managed Objects") says:
You can sometimes benefit from creating your own unique ID (UUID) property which can be defined and set for newly inserted objects. This allows you to efficiently locate specific objects using predicates (though before a save operation new objects can be found only in their original context).
But the NSManagedObjectContext documentation says you "absolutely must not override" objectID.
So, how does one properly set a custom object ID?

Reading through the documentation I think it is suggesting that you create an additional property on your object that stores your own UUID (the ID from CouchDB in this case) rather than overriding objectID. You can then use a predicate to search against your own UUID property you created and stored the CouchDB ID in. Note that you must perform a save operation first if you are searching outside of the original context.

Related

How is idProperty used for more complex schema? Dojo dmodel

It’s not very clear how idProperty is used in the data store when building a data model. The documentation says “If the store has a single primary key, this indicates the property to use as the identity property. The values of this property should be unique. This defaults to "id".
Is this assuming the schema from which the model is based, has a mostly flat structure? For example an array of objects – each with an identity property?
What if the schema is not a simple array but has more complex structure starting from a single object that contains several sub levels of properties within properties. OR is just multiple arrays on the same level where each group of arrays identify property are independent of one another?
A store is an extension of a collection.
A collection is the interface for a collection of items (your obect with a potentially complex schema).
You can use Custom Querying on a collection to define special queries to find your data with any subset of properties.
In short, yes you can querying your data even if it has a custom schema but you need to define a Custom Querying.
More info can be found here at the end of the article: https://github.com/SitePen/dstore/blob/master/docs/Collection.md

Where do I place the Ensembles uniqueIdentifier?

I have an app that has threee (3) entities in a CoreData store managed by MagicalRecord; I have one (1) managedObject for the whole app. On page 28, the book states:
“Assuming you have added a uniqueIdentifier attribute to your managed objects,”
Does this mean that I need a uniqueIdentifier for each of the entities, or will one do? If I only need one, which entity should I put it in, or doesn't it make any difference. (the example only has 1 entity, hence the question) :-}
Each entity needs an attribute for the unique identifier. The value should be unique for each instance of that entity.
The value of the unique identifier must be unique among other instances of the same entity type.
If you have three entities, Entity1, Entity2, and Entity3 then you can have an instance of Entity1 with identifier '42' and an instance of Entity2 with identifier '42 and another instance of Entity3 with identifier '42' without causing any problems.
EDIT
You say each entity needs an attribute... which should be unique for
each instance of that entity. The value must be unique among other
instances... but then you give examples of Entity1, 2 and 3 where the
identifier is the same for all three! I'm confused... – SpokaneDude
That's correct. Entities describe the attributes and relationships for a class of managed objects (which is why the class that represents an entity is named NSEntityDescription). The entity itself is not a managed object.
So, for each entity defined in your model, you need to have a unique identifier attribute. The value of that unique identifier must be unique among instances of that particular kind of entity.
If you have 100 instances of Entity1 then each of those instances must have a different value for the unique identifier, relative to all other instances of Entity1.
If you have 100 instances of Entity2 then each of those instances must have a different value for the unique identifier, relative to all other instances of Entity2 but they don't have to be unique among the identifiers for the instances of Entity1 because the identifiers must be unique per-entity.
OK, one last question (I hope). The app is for bookstores; does each
unique bookstore have one (1) UUID that they share amoung the
different employee's iPads? and if I have another app (say for
barbershop scheculing), is the UUID different than the bookstore's
UUID? And lastly, does the UUID value ever change for a particular
bookstore? – SpokaneDude
So, I assume your core data model has an entity named Bookstore with some number of attributes. You need to make sure that one of those attributes will uniquely identify each managed object instance of entity Bookstore.
If you have an attribute name and you know for certain that you will never have two Bookstore instances with the same name, then you can use name as your unique identifier.
However, if there is the possibility that there may be more than one object instance that may have the same attributes, yet still represent a different object, then you need a special attribute whose sole purpose is to guarantee uniqueness.
For example, let's say your application sucks down JSON data from a server. At the same time, your user runs the app on their iPad and iPhone. They both read a record that describes a Bookstore with name "Bob's Books" and address "42 Mall Drive."
Each device creates the instance in their local database.
When it comes time to synchronize those two instances, how does the synchronization algorithm know if you have two completely different objects with the same value, or if you have two copies of the exact same object?
That's where the unique identifier comes in. You tell the ensembles framework which attribute of each entity can be used to tell if the objects are really the same or not. Then, when it sees two different objects, it can look at the unique identifier and determine if the two objects are really the same object, or if they are two completely separate instances.
Thus, for each entity, you need to either ensure that one of the attributes can always be used to uniquely identify objects in this manner. If you don't have such an attribute in your model, then you should add one for the entity, and make sure that the attribute is unique among instances of that particular entity.
The unique identifier only has to be unique among instances of the same entity, within the same database. However, when I have not had a certain unique attribute, I have been using NSUUID to generate my unique identifiers.
Create „guid” property or something similar on each entity and set it to UUID on each new record (and all existing too).
Check ensembles example.

Neo4J node_auto_indexing and relationship_auto_indexing

I want to know, if the two settings node_auto_indexing and relationship_auto_indexing in the neo4j.properties concerning the ids of nodes and rels?
or creates neo4j automatically an index for the ids of the inserted nodes and rels?
the auto index creates index for all properties defined at the *_keys_indexable line in the neo4j.properties file.
the index then bounds the node ID with the specific property value. thus, searching the index for the the property value will return the node.
since your question is a bit unclear to me, you might want to take a look at official docu:
http://docs.neo4j.org/chunked/milestone/auto-indexing.html
No you shouldn't add your ID to the auto index. There is no use for it, since you can already retrieve nodes by ID, without using auto index.
There are however occassions where the usual ID is not sufficient. For instance, when working with users, you may have a user id of some kind. You'd then store this in a property, and add that property to the auto index. This way, you can search by user id. Underlying, Neo4J matches your custom user ID, with the actual node id.
Important to keep in mind here is that per definition, auto index is not unique. You need to design your application in such a fashion that the property is in fact unique, if you're expecting a single node result.

Unique Identifier for NSManagedObject

I have a need to obtain a unique identifier for a type of NSManagedObject I've created. It needs to be available as soon as the object has been created, never change, and be completely unique.
This rules out the NSManagedObjectID, as this can change when the context is saved. I believe the -hash method could be non-unique if my objects have the same properties.
I'd really like to avoid creating an otherwise useless uniqueIdentifier UUID field on the entity as this seems wasteful and messy. Is there an accepted best practice here?
try the URIRepresentation property of NSManagedObjectID. this is very unique ID for the current NSManagerObject but be careful until the NSManagedObject is not saved it gives you a temporary ID only, not a permanent one and they might be different. (I'm just saying it because I don't know for what and how you want to use the unique ID.)
UPDATE #1
this is not an imaginary unique ID only, this is pure unique URL for each individual NSManagedObject (like every file has a unique URL), using them you can find again the original NSManagedObject, after you lost their pointer. I know it is hard to understand, but this is the point of the NSManagedObjectID and its properties.
(if you don't understand how the CoreData and their objects work, you would not downvote the answer. please, read more documentation instead of the pointless downvoting.)
UPDATE #2
according to #NickLocking comment, I would extend the bold part of my answer above:
until saving the NSManagedObjectContext for the the new and still unsaved NSManagedObject classes has a temporary unique ID only. They will get the permanent unique ID after they are saved at first time.
Eventually I have decided that there is no good way to do this, so I just created a uniqueIdentifier field that I apply a UUID to on awakeFromInsert.
Saving the object causes other parts of my application, specifically NSFetchedResultsControllers, to update before I'm finished with the object. I briefly tried NSManagedObjectContext's obtainPermanentObjectIds:withError: method, thinking it would obtain the object IDs without saving the context, but in fact it does simply save the context.
The only unique identifiers provided automatically by CoreData is the object ID, but as you have noted it will change after it is initially created. But before you go coming up with another way to work around this, you might want to consider defining something like the following in your managed object class:
- (NSManagedObjectID *)permID {
if ([[self objectID] isTemporaryID]) {
// Save myself, returning nil if there are errors
}
return [self objectID];
}
This approach isn't perfect by any means, especially if you need to expose the permanent ID before the object is in a state where it is valid and can be saved to the database. But it will allow you to expose a permanent ID in a consistent way as long as you don't need it before the object can be saved.

Should one include ID as a property on objects persisted to a database?

I am creating the model for a web application. The tables have ID fields as primary keys. My question is whether one should define ID as a property of the class?
I am divided on the issue because it is not clear to me whether I should treat the object as a representation of the table structure or whether I should regard the table as a means to persist the object.
If I take the former route then ID becomes a property because it is part of the structure of the database table, however if I take the latter approach then ID could be viewed as a peice of metadata belonging to the database which is not strictly a part of the objects model.
And then we arrive at the middle ground. While the ID is not really a part of the object I'm trying to model, I do realise that the the objects are retrieved from and persisted to the database, and that the ID of an object in the database is critical to many operations of the system so it might be advantageous to include it to ease interactions where an ID is used.
I'm a solo developer, so I'd really like some other, probably more experienced perspectives on the issue
Basically: yes.
All the persistence frameworks ive used (including Hibernate, Ibatis) do require the ID to be on the Object.
I understand your point about metadata, but an Object from a database should really derive its identity in the same way the database does - usually an int primary key. Then Object-level equality should be derived from that.
Sometimes you have primary keys that are composite, e.g first name and last name (don't ever do this!), in which cases the primary key doesn't become 'metadata' because it is part of the Object's identity.
I generally reserve the ID column of an object for the database. My opinion is that to use it for any 'customer-facing' purpose, (for example, use the primary key ID as a customer number) you will always shoot yourself in the foot later.
If you ever make changes to the existing data (instead of exclusively adding new data), you need the PK. Otherwise you don't know which record to change in the DB.
You should have the ID in the object. It is essential.
The easiest use case to give as an example is testing equality:
public bool Equals(Object a, Object b) { return {a.ID = b.ID}; }
Anything else is subject to errors, and you'll find that out when you start getting primary key violations or start overwriting existing data.
By counterargument:
Say you don't have the ID in the object. Once you change an object, and don't have it's ID from the database, how will you know which record to update?
At the same time, you should note that the operations I mention are really private to the object instance, so ID does not necessarily have to be a public property.
I include the ID as a property. Having a simple unique identifier for an object is often very handy regardless of whether the object is persisted in a database or not. It also makes your database queries much more simple.
I would say that the table is just a means to persist an object, but that doesn't mean the object can't have an ID.
I'm very much of the mindset that the table is a means to persist the object, but, even so, I always expose the IDs on my objects for two primary reasons:
The database ID is the most convenient way to uniquely identify an object, either within a class (if you're using a per-table serial/autonumber ID) or universally (if you're maintaining a separate "ID-to-class" mapping). In the context of web applications, it makes everything much simpler and more efficient if your forms are able to just specify <input type=hidden name=id value=12345> instead of having to provide multiple fields which collectively contain sufficient information to identify the target object (or, worse, use some scheme to concatenate enough identifying information into a single string, then break it back down when the form is submitted).
It needs to have an ID anyhow in order to maintain a sane database structure and there's no reason not to expose it.
Should the ID in the object read-only or not? In my mind it should be read-only as by definition the ID will never change (as it uniquely identifies a record in the database).
This creates a problem when you create a new object (ID not set yet), save it in the database through a stored procedure which returns the newly created ID then how do you store it back in the object if the ID property is read-only?
Example:
Employee employee = new Employee();
employee.FirstName="John";
employee.LastName="Smith";
EmployeeDAL.Save(employee);
How does the Save method (which actually connects to the database to save the new employee) update the EmployeeId property in the Employee object if this property is read-only (which should be as the EmployeeId will never ever change once it's created).