Apple's documentation suggests the use of inverse relationships when modelling data models in CoreData.
I have the following example:
A Book (Entity) has several "pages" and one "frontCover" and one "backCover".
A Page (Entity) is in one "book" (so "book" is the inverse of "pages").
OK so far, that's the standard case...BUT now, my problem:
I only have one class Cover (Entity). A Cover (Entity) is on one "book". On this "book" the Cover is EITHER the "frontCover" OR the "backCover". So, the inverse of "book" is EITHER "frontCover" OR "backCover".
This cannot be modelled in CoreData. A relationship can only be the inverse of one relationship, but not of EITHER this OR that relationship.
What is the best way to model this? Unidirectional relationships (no invers)?
Thanks for your answers,
Chris
You could do something like the model below (first image). This would leaving of Cover's inverse relationships as nil. This doesn't feel right to me, though.
Another option (second image) would be to give Book a 'covers' relationship which references 2 Cover objects, and give Cover an isFront boolean attribute. This would allow for inverse relationship called 'book'.
One way to do it could be to create Cover as an "abstract" entity with two sub entities - FrontCover & BackCover. Then you could create the relationship & inverse to each of those.
I just want to add.
One way is to have 2 subentities. But that's useful only if FrontCover and BackCover differs a lot.
If they are exactly the same object, you should instead use an enum in the entities.
That enum differentiate whether the cover is frontCover or BackCover.
Then you set only 1 "to many" relationship from book to cover.
The purpose of coredata is to save your data. Your logic should be in the code anyway.
Also creating two subEntities is essensially the same with westSider's answer. Sub entities simply add another relationship on the original one.
Related
I am new to CoreData environment and I'm trying to understand how it works.
In my project, I have a superclass VetExam whose subclasses are Examination, Treatments and Vaccination, which share the same attributes of their superclass and has a reference to Pet class. On the other hand, Pet class holds an array of reference of every class except of VetExam, which should only be used for Polymorphism (so that I can use VetExam object and create a single view for each type).
Based on this model, I've tried to create entities in CoreData, but it seems that I have to specify for each type the inverse relationship for each entity. This represent a problem since from VetExam entity side the relationship is of type Pet but on Pet side is To-Many for each type of Examination, which does not allow me to get the inverse reference of VetExam.
Since this explaination can easily be misunderstood, I will show you the visual representation of it.
The problem is in VetExam entity, whose Inverse attribute is not known.
Does anyone know how to deal with this type of situation?
A preliminary note on inheritance...
Class inheritance
AND
Entity inheritance
For the second, I highlight the note in the Apple Documentation:
Be careful with entity inheritance when working with SQLite persistent
stores. All entities that inherit from another entity exist within the
same table in SQLite. This factor in the design of the SQLite
persistent store can create a performance issue.
What this means is that Core Data framework creates one large table in the SQLite database that includes the parent entity and the child entities. Such a large table inherently contains inefficiencies. While this may seem convenient for you to manage now in your model editor and in your NSManagedObject subclasses, this may cause inefficiencies / performance issues in the long run if you expect your app to persist and retrieve large amounts of data in the four entities you mention.
Advice from others is very relevant here because four separate entities will in my humble opinion be easier to manage, rather than one parent entity and three child entities. You do not have to give up the class inheritance you’ve developed in your code if you choose this option.
So, to answer your question...
My logic:
Every Pet may have many instances of VetExam during its life, but each instance of VetExam is carried out on only one Pet?
If yes, then create a one-to-many relationship between Pet and VetExam -
Pet <—>> VetExam.
Whatever occurs during the VetExam is any combination of one Examination, Treatment and/or Vaccination. That is and in an attempt to be clear, the VetExam may optionally have an examination, but it may not have a treatment or a vaccination. This is likely to change for each VetExam, therefore this is directly related to the VetExam, not the Pet.
If yes, then create optional one-to-one relationships between VetExam and the entities Examination, Treatment and Vaccination.
VetExam <—> Examination
VetExam <—> Treatment
VetExam <—> Vaccination
In this model, each entity relationship detailed above has an inverse.
Finally, it might be worth noting that in this proposed model, the relationship between a Pet and all the examinations, treatments and vaccinations it receives during its lifetime is stored against PetExam, not directly against the Pet.
I'm a bit confused about this naming convention.
What is the difference between them and are target/source interchangeable with owning/not owning?
One thing in particular is hard to understand:
"The main difference between a OneToOne and a ManyToOne relationship in JPA is that a ManyToOne always contains a foreign key from the source object's table to the target object's table, where as a OneToOne relationship the foreign key may either be in the source object's table or the target object's table"
JPA wikibooks
I can't imagine such situation in uni one-to-one
Differences between them are a little confusing. You should practice a lot to understand very well.
At first, you should understand some terminology:
Role : In every relationship there are two entities that are related to one another, and each entity is said to play a role in the relationship.
Direction : Relationships can be unidirectional or bidirectional. For e.g.. a Person has an address is normally unidirectional whereas Employee working on a project is normally bidirectional. We will look at how to identify and define directionality while coming up with a Data Model.
In order to have relationships at all, there has to be a way to create, remove, and maintain them. The basic way this is done is by an entity having a relationship attribute that refers to its related entity in a way that identifies it as playing the other role of the relationship. It is often the case that the other entity, in turn, has an attribute that points back to the original entity. When each entity points to the other, the relationship is bidirectional. If only one entity has a pointer to the other, the relationship is said to be unidirectional. A relationship from an Employee to the Project that they work on would be bidirectional. The Employee should know its Project, and the Project should point to the Employee working on it. A UML model of this relationship is shown here. The arrows going in both directions indicate the bidirectionality of the relationship (Form this book >> Pro JPA 2)
Then dive into this link (archived from the original)
I'd like to comment only the links, but I need 50 reputation
If I have two entities; Foo and Bar. And Foo has two properties; bar1 and bar2 of type Bar. Now does Foo have a one-to-many releationship to Bar? At least should it be modeled as that in Core Data? Or is it two one-to-one releationship? How do I set that up properly in Core Data with inverse? The one-to-many releationship I understand but not the last releationship type? Is that even possible or good way to that?
And Foo has two properties; bar1 and bar2 of type Bar. Now does Foo
have a one-to-many releationship to Bar?
No, Foo has two relationships with Bar, and those relationships are named bar1 and bar2. Whether they're "to-one" or "to-many" depends on how you specified them. Select each in the model and see whether the "to-many" checkbox is checked.
At least should it be modeled as that in Core Data?
That depends on what you're trying to model. Do you want to have two separate relationships to specific object (that'd be two different "to-one" relationships), or do you want a single relationship to a group of objects (one "to-many" relationships)? Here's an example that might help clarify things...
A business may have zero or more employees. A business also has a single chief executive officer and a single chairman of the board. So the Business entity might have a "to-many" relationship named employees with the Person entity. It might also have "to-one" relationships named ceo and chairman, again with Person. Those might not be strictly necessary -- maybe the CEO and Chairman are both employees, so you could find them by searching the set of employees and filtering by job title. But it can be handy to have them as separate relationships if you're going to use them often and don't want to have to search through thousands of other employees every time you do.
How do I set that up properly in Core Data with inverse?
Again, it'll depend on what you're modeling. For example, the inverse of the employees relationship would be Person's employer "to-one" relationship.
Entities have several different kind of properties, they have attributes and relationships (and fetched properties, but that's beside the point). It sounds like Foo and Bar are two classes you created with Foo having Bar properties. Then you want assimilate those as Entities in a Core Data model.
Typically, things are done the other way around. You create Entities in the Core Data model editor. You then link the entities by creating relationships. If you add a relationship from Foo to Bar, then it is good practice to create an inverse relationship from Bar to Foo.
Create the relationship from Foo to Bar
Create the relationship from Bar to Foo
Select that last relationship and set its inverse to the first one
Now if you want Xcode to generate the matching NSManagedObject subclasses Foo and Bar, then you can select the Entities and in the Xcode Editor menu, select "Create NSManagedObject subclasses"
You'll then see you're two classes with the proper attributes to match how your model is set up.
I've authored a book on Core Data that explains all this is much deeper details.
This is two one-to-one releationship.
To make inverse just select you entity in inverse field (When you create relation).
Re the Core Data table below. I want to associate the "Color" entity with the "detailsColor" attribute (in the Details entity). The idea is that there are (in this case) three Colors applicable to detailsColor.
I would have thought the "Relationships" in Color would apply to the "detailsColor" attribute as these colors only apply there. I cannot seem to connect the two though. I can only create a relationship with the entire Details entity. Is this correct? Suggestions appreciated.
A relation connects entities, so it doesn't make sense to say that "colorDetails" applies "to the entire Details entity". Your set up looks okay to me.
In Core Data, most of the time relationships are modeled bidirectional. But the docs say in another place:
It typically only makes sense to model
a to-one relationship in one
direction.
Within Core Data you should always use a bi-directional relationship unless you have an extreme edge case. If you use one directional relationships then you are going to incur performance penalties within core data itself as well as have issues with referential integrity.
Unless you know specifically why you need a uni-directional relationship then you should always do a bi-directional relationship; the rule is that simple.
While Franci's answer is interesting, I have to disagree with it. Even in the examples he provided you should have a bi-directional relationship. There are almost no situations where a uni-directional relationship is going to be a better fit.
The answer is determined by the referential integrity requirements you want to enforce. If updating or removing the object on either side affects the object on the other side of the relationship, you need two-way. However, if updating/removing the object on one side does not affect the object on the other, then a one way is a better model.
Take for example a parent-children model with a 0..n : 1 cardinality (I prefer the 1 : 0..n representation, but for the sake of argument let's reverse it). Adding a new child, updating an existing child or deleting a child has no effect on the parent object, so there's no need for the parent to know explicitly about all the children (except when it comes time to pay college tuition). However, removing the parent has an adverse effect on the children objects, as they need to be deleted or re-parented, otherwise are orphaned and in an invalid state. Thus, it's better to model it as a one-way relationship. Another example is inventory - parts catalog relationship, again with 0..n : 1 cardinality.
It's a matter of ownership: usually it doesn't make sense to have a bidirectional relationship because an entity conceptually owns the other one.
Think about some examples. If you have a structure in which you have users and an user can have a simple bank account associated with him. If you make the relation bidirectional you mean that an user owns an account but also an account owns an user.
This will make sense because you don't want to delete an user whenever you delete his account. That's why usually you don't need to have it bidirectional: because it's an additional constraint that is not needed since most of the time you will have an entity that has the other but not vice-versa.
I think you read the whole document about relations you referenced in your question.
The document also describes all disadvantages of using unidirectional relations, and that only under very rare circumstances it makes sense to create unidirectional relations.
As a general rule i would strongly recommend creating bidirectional relations, except you are knowing exactly why not to do so.