Relationships and entities in CoreData - iphone

I have three entities, A, B and C.
Where A has a to-many relationship with B
and B has a to-many relationship with A
Then C has a to-one (correct terminology?) relationship to A, and a to-one relationship to B.
However I want it so C's relationship with A must be an instance of A that is in a relationship with the B related to C.
Normally in code I'd use NSArrays in place of relationships and then in C have store the index of the needed instance. This is my first time using CoreData, so I'm unsure about most of it.
EDIT: To clarify:

First, it'd be easier to discuss your situation if you'd avoid using b to mean several different things. There are four relationships in your diagram; for the sake of the discussion, you could name them d, e, f, and g.
To answer your question, you can't and don't need to include the kind of restriction that you're talking about in the model. The model defines relationships between kinds of managed objects, but it doesn't say anything about individual objects. It's usually better to try to think in terms of objects when you're learning Core Data, but you should know that the entities you define in the model are analogous to tables in a relational database: they define can be stored, not what the code should or must (or must not) store.
To restrict C.a to one of the A's in C.b.bs, you'll need to write some code. If C.a is only set in one place, you might choose to implement the restriction in that code. If the restriction is essential to the proper operation of C, you might instead (or in addition) choose to add a check to the setter for C.a that verifies that the A is one of the allowed ones. You may also need to fix up the setter for C.b so that if C.b changes, it verifies that C.a is still valid and does something appropriate if it's not (clear C.a, pick a new C.a, refuse to accept the new C.b, post a notification, throw an exception, whatever).

Related

Core Data Inheritance - Manage Inverse relationships of subclasses

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.

Is it possible to infer indirect relationships in Sparx EA?

I have three components, A, B and C, and I associate A to B and B to C. If I create a new diagram and drop these three components onto the diagram, EA automatically shows the relationships between the components.
If I only drop A and C on a new diagram, is there a way to get EA to show that A is associated to C without creating an explicit association between A and C?
Whilst this is not a default behavior in EA, and some EA practitioners even argue against such a request.
I've seen one of my client in a similar situation, where there was a need to traverse from a business process to use cases without adding the requirements on to the picture (Their usual hierarchy business process -> Requirements -> UCs)
We ended up automating trace connectors creation in this particular instance. Where everytime a requirement is linked to a usecase, and if the same requirement is linked to a business process, a trace relationship is created between UC & BP.
NB - This could end up in really messy relationships, if you don't constraint it for specific purpose
The Associations A->B and B->C imply nothing about any potential relationship between A and C. For example, if the Association between B->C defines that B has a private attribute of type C, then A may not even know that C exists. Creating an explicit relationship is the way forward.
To what the other posters have said, I'll add that implicit relationships are simply not part of UML. So I don't see EA supporting it any time soon. If you really need it, Nizam Mohamed's automation suggestion will work but you can't get EA to do it out of the box.
If it's enough to see these implicit relationships on demand, you can use EA's Traceability window (under the View menu). This lets you follow relationships between elements in a tree view, so you can navigate from A to B to C.

What is the difference in ECore between containment and reference?

When creating references between ECore entities there is the possibility to mark a reference as "containment".
Can somebody explain me in easy words what's the difference between a plain reference and a containment? The definitions and explainations I found so far didn't do the trick for me.
Reference: A reference is a plain "A knows B" relation. Separate references do not influence each other. A can know B and B can know C. Hence, if you have A, you can go to C over B. If you remove the reference, A, B and C will still exist, they just don't know each other any more.
Containment: A containment is the "A has B" kind of relation. Usually used for lists, e.g. "A has multiple B". ECore/EMF can then perform atomic commands on such collections, such as move all objects from one containment to another. It can also enforce constraints, such as a minimum amount of contained objects or a maximum amount of contained objects, or ensuring that the contained object is not contained in any other containment.
Example:
Assume you have an object called ShoppingCart with a reference called Customer and a containment called OrderedProducts. The OrderedProducts has a reference to a Product.
What does this model tell you?
You can assign a Customer to the ShoppingCart. If you remove the Customer from the ShoppingCart, the Customer object itself will still exist (e.g. in the database)
The OrderedProduct objects need a ShoppingCart to exist. If you remove one from the ShoppingCart, it will cease to exist.
Each OrderedProduct has a reference to an existing Product in the database. If you remove one of the OrderedProducts from the ShoppingCart, the Product in the database will still be there - just the order of that product for that specific customer is gone
Reference : can be like association in UML
Containment : is the composition relation from UML
Also this can be seen in the EMF diagram, if you set the containment to true, then the line will have a filled side, showing the containment/composition. This is what I have observed.

Is it good practice to model to-one relationships in only one direction? Or must they be modeled in two directions?

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.

Inverse relationship warning - ask for practices on using inverse relationship

I have the Order table which contains information about a specific order, (when does it start, how many people, etc...) and that Order table has To-Many relationship to Menu Item table. I call that relationship "orderItems".
The compiler gives me warning, "Order.orderedItems -- to-many relationship does not have an inverse: this is an advanced setting (no object can be in multiple destinations for a specific relationship)"
How do you normally do for inverse relationship? Do I need to create a new relationship on the Menu Item to point back to Order, and set the inverse relationship to the "orderedItems"? (In fact, there is no reason for me to save that data in the Menu Item table)
Someone can explain to me why, or at least, point me the reason on why I need to create the inverse relationship on the Menu Item table.
Thanks in advance,
I ran into this warning and problem too! Here's what you need to know...
Lets say you have two tables - Cars and Drivers. You define a one-to-one relationship - one car to one driver, but no inverse.
So now, if you create a car and assign it a driver, if you delete the driver later, and then try and access car.driver, your program will crash. Car.driver will not be nil - it will crash your program.
So, if you don't create an inverse, you can't ever check to see if something is nil, and you can't even safely work with car.driver at all if driver has been deleted.
I don't like how XCode has this set up. It should default to inverse and be a pain in the ass to change it.
Setting up an inverse is simple. Just open your xcdatamodel in XCode, click the existing relationship, and check the inverse box.
Typically you should always add the inverse relationships.
Do not think about Core Data in terms of the tables that will be generated. In fact, Core Data is smart enough not to put the data in more than one table.
Focus on designing a data model that will meet your needs (and add the inverse relationships).