I am a little fuzzy about Core Data Relationships deletion rules. So if someone could help me answer a few questions about them.
I have Entities A and B. A has a to-Many relationship with B, and B has a to-One relationship with A.
A<--->>B
Now, if I set the delete rule at A to Cascade, I understand it will delete all the Bs related to it. But if I set it to Nullify, will it set the Bs to NIL or just the Foreign Key to Nil?
And I looked everywhere about the relationship from B to A, should I set it to Nullify? Will that just Nullate the "B Object" at A? Or will it Nullify all the Bs associated with A? What about Cascade? Will it delete all the Bs associated with A, or just the particular B?
Or do I just use "No Action" on the relation from B to A so that when I delete B, no change will happen to A, but the reference to B won't exist?
I am PRETTY confused with these, so excuse my questions.
Thanks.
If you set the delete rule to "nullify" and delete the A object, then the references to that object in the Bs will be removed. The inverse works the same way. If you have cascade and delete B then it will remove the A that B pointed to. It will then follow the delete rule from A to the remaining Bs (either cascade or nullify).
The rules you set really depend on your data model. If A were a customer and B were their orders then you could set the A->B rule to deny (prevent A from being deleted if it the customer has orders) or cascade (delete the orders when the customer is deleted). The B->A rule would probably be "nullify". If an order is deleted simply remove the reference to the order from the customer.
The relationship delete rules are described in the Apple Core Data Programming Guide
More deep explanation and visualization with delete rule.
Let be assume we have database with table person and work. Single person can have many tasks to do.
Sample data and ER relationship
Delete Rule Explation
No Action : If I add this delete rule on relationship and then delete one of the person then it will not do anything with the task but person got deleted. The task still points to the person that we deleted.
Use Case: I don't think it is used anywhere.
Nullify : If I apply this delete rule and delete the person then associate tasks will points to the null person. For example, I deleted the thor and thor tasks will point to the null person. Check below output.
Use Case : Let's assume we have DB with Person and address. Now person sells his house to broker. In this case you can null the person of that address and reassign the owner to that house when new Person purchased that house.
Cascade : In this rule, if I deletes the person then it will deletes all the tasks associated with that person. For example, I deletes the Spiderman, check below output.
Use Case: Let be assume we have a user and his friends list. If user account deleted then we also want to delete the friend list.
Deny : Now we have person i.e. IronMan with 2 tasks. In this rule, if I try to delete the Iron Man then it does not allow me to do. It gives error "The operation couldn’t be completed. (Cocoa error 1600.)" on saving the context. Now to delete the Iron Man person, we need to delete all his associated tasks and then we could able to delete the Person.
Use Case: Lets assume, there is a user with bank account. We can not delete the user from the bank until his account is not closed.
if you set "nullify" and delete A's object , A's object and the back relationship only will get deleted not B's object.
eg : Customer entity has nullify relationship to orders . and if you delete a customer from customer entity, it will just delete customer and its back relationship from order . it wont remove the orders the customer made
but if the relationship is "cascade" it will remove the customer and his orders .
if it is "deny" . if the customer has any order , it wont delete delete the customer even .
Related
Suppose I have two entity named Book and Publisher
1. Book has attribute :- writer, title.
2. Publisher has attribute :- name, type
I set a relationship :- Publisher to Book ( one to many and set it as inverse relation)
With relationship selected I can see in DataModal inspector a row called Delete Rule with three options 1. Nullify 2. Cascade 3. Deny
What these are and I want to delete Publisher entity only if I delete the last Book
Thank You in advance.
I'm just a beginner
:)
The docs do a good job explaining these delete rules
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/HowManagedObjectsarerelated.html
Relationship Delete Rules
A relationship's delete rule specifies what should happen if an
attempt is made to delete the source object. Note the phrasing if an
attempt is made. If a relationship's delete rule is set to Deny, it is
possible that the source object will not be deleted. Consider again a
department's employees relationship, and the effect of the different
delete rules.
Deny If there is at least one object at the relationship destination
(employees), do not delete the source object (department).
For example, if you want to remove a department, you must ensure that
all the employees in that department are first transferred elsewhere
(or fired!); otherwise, the department cannot be deleted.
Nullify Remove the relationship between the objects but do not delete
either object.
This only makes sense if the department relationship for an employee
is optional, or if you ensure that you set a new department for each
of the employees before the next save operation.
Cascade Delete the objects at the destination of the relationship when
you delete the source.
For example, if you delete a department, fire all the employees in
that department at the same time.
No Action Do nothing to the object at the destination of the
relationship.
For example, if you delete a department, leave all the employees as
they are, even if they still believe they belong to that department.
It should be clear that the first three of these rules are useful in
different circumstances. For any given relationship, it is up to you
to choose which is most appropriate, depending on the business logic.
It is less obvious why the No Action rule might be of use, because if
you use it, it is possible to leave the object graph in an
inconsistent state (employees having a relationship to a deleted
department).
If you use the No Action rule, it is up to you to ensure that the
consistency of the object graph is maintained. You are responsible for
setting any inverse relationship to a meaningful value. This may be of
benefit in a situation where you have a to-many relationship and there
may be a large number of objects at the destination.
I have a question about CoreData relationships.
I have this situation:
I have DOG and BONE entity.
Each DOG can have more BONE.
Each BONE can have more DOG.
So I need a many to many relationship.
how do I set the report delete in CoreData? what kind?
I think I need something as this:
When I delete a BONE I do not have to remove the DOG;
When I delete a DOG I do not have to remove the BONE if this is used from a DOG.
When I delete a DOG I have to remove the BONEs if these are used only from this DOG.
Is this mechanism automatic for CoreData if I impose this relationship type?
About insert?
For example: I need to insert a DOG with some Bones: How do I check if the bone already exists?
Every bone in my table has an ID
First of all, it is difficult to get a handle on your example as it doesn't make intuitive sense. That being said, ignoring the entity type, if you have an entity A and B with a mutual to-many relationship (many-to-many).
Apple: Relationships and Fetched Properties
(for the sake of brevity assume 'entity' = 'entity instance' below)
To Insert:
You must insert both entity A and insert entity B. Core data will not
automagically create entity B if you create entity A, just because they have a relationship
If you wish to associate an existing entity B to a new entity A, then
you must insert entity A then link entity A to entity B via the
relationship. Just because you defined the relationship in the object model, doesn't mean the objects will be automagically related when you insert them. you need to explicitly do this
To Delete:
Coredata will allow you to set the 'relationship delete rules'. This will govern what happens when you delete an object on one end of the relationship. You must set the rules on each end as you may choose to delete either entity A or entity B. Delete rules include: deny, nullify, cascade, no action. Check out Apple's doc on this to get you question above answered (it is clear).
To apply your example to the delete rules:
When I delete a BONE I do not have to remove the DOG; (no action)
When I delete a DOG I do not have to remove the BONE if this is used from a DOG. (deny or nullify)
When I delete a DOG I have to remove the BONEs if these are used only from this DOG. (cascade)
In the example of using "intermediate join entity"
To find out who one person’s friends are, you have to aggregate all the friend destinations of the friends relationship, for example:
NSSet *personsFriends = [aPerson valueForKeyPath:#"friends.friend"];
Is above line of code getting a given person's MUTUAL friends? or just ONE-WAY friends, which means only getting "peoples who are treated by this given person as his friends"?
I am not certain, because "To find out who one person’s friends are" sounds like ONE-WAY friendship (that could be why there is a strange relationship befriendedBy represents those who count the source as their friend. FriendInfo represents information about one friendship, “in one direction.” .)
This is a really confusing example. There are two possibilities.
In most cases being "friends" is a mutual thing. In this case you would have a self-referencing many-to-many relationship of a Person, perhaps called friends. The relationship would be mutual.
You seem to be implying that it is possible to add another person as a friend even if that person is does not reciprocate. In order to lift the confusion give this many-to-many relationship another distinct name, e.g. contacts. This would be the Persons that have been added unilaterally. In Core Data, all relationships are best modelled as mutual, so you can use another relationship potentialFriends that is the inverse relationship of contacts. Maybe there are better names, but you get the idea.
The intermediate join entity is only necessary if you want to store additional attribute with a particular relationship, e.g. the date a contact request was made. In this case, you would have the join entity e.g. friendLink, which would have a to-one relationship to two distinct Persons. You can model the state of the link (unilateral or mutual) in this entity.
If I delete a CoreData record from an entity, does that also delete the relationship that record had with another record in another entity?
It depends on the Delete Rule that you have enabled for the relationship. The Core Data Programming Guide documents these (extracted below). Have a look in the inspector to see which option you have set for your relationships. If you have a specific data model which you want comment on you should edit your question to be more specific.
Deny
If there is at least one object at the relationship destination, then the source object cannot be deleted. For example, if you want to remove a department, you must ensure that all the employees in that department are first transferred elsewhere (or fired!) otherwise the department cannot be deleted.
Nullify
Set the inverse relationship for objects at the destination to null. For example, if you delete a department, set the department for all the current members to null. This only makes sense if the department relationship for an employee is optional, or if you ensure that you set a new department for each of the employees before the next save operation.
Cascade
Delete the objects at the destination of the relationship.
For example, if you delete a department, fire all the employees in that department at the same time.
No Action
Do nothing to the object at the destination of the relationship. For example, if you delete a department, leave all the employees as they are, even if they still believe they belong to that department.
I have two entities: patient and checkpoint.
Patient has attributes such as DOB, name, ID, etc.
Checkpoint has attributes such as dateRecorded, height, weight, etc.
You probably get the idea- I want there to be a set of patients, and then each patient can have checkpoints associated with that patient.
On both entities, how should I set the settings? The settings are:
I looked at the documentation for this, and I was still confused. I think what I want is a one to many relationship (for patient), but then I'm not sure how to set the inverses for either of them, or the delete rule and the other stuff. THANK YOU!!
I just got started with Core Data this week. Great question!
Relationships:
Since one patient can have many checkpoints, the Patient to Checkpoint relationship is a One to Many relationship. The concept of an "inverse relationship" is essentially this: You've got a relationship going one way (Patient to Checkpoint) - now go ahead and look at it from the inverse, the Checkpoint's perspective. A checkpoint can apply to only a single patient. Therefore, the Checkpoint to Patient relationship is a One to One relationship.
Inverse Relationships:
To handle the inverse relationship, simply create each relationship, ignoring the inverse. Then, after you have the relationship on each object, go ahead and define the inverse as the relationship on the other entity.
In other words, a relationship points to another entity or a group of entities. An inverse relationship points to a relationship on another entity.
Delete Rules:
As far as delete rules are concerned, it's fairly simple. When trying to delete a patient which has checkpoints...
Deny: Core Data won't let you delete the Patient.
Cascade: Core Data will delete the Entity (Patient), as well as cascading through relationships and deleting those objects as well. (In other words, Core Data will delete the Checkpoint objects too.)
Nullify: Core Data will delete the patient but first remove the relationship. The Checkpoint will remain intact.
For the Patient entity might want either deny or cascade, depending on how you want to manage your data. Based on your usage case, you probably don't want nullify, since Checkpoints are dependent upon Patient entities.
You want nullify for the Checkpoint, since the Cascade would prevent you from deleting a checkpoint without deleting the entire patient, and Deny would effectively force the same.
Based on the scenario mentinoed, it looks like a one to many relationship between patient and checkpoint tables.
Now add a relationship from “Patient” to “Checkpoint”, and also set the inverse between the tables.
Also, set the delete rule for both relationships to “cascade”. This means that if you delete one object with Patient, the corressponding Coredata will delete the associated object as well.