Coredata delete rule confusion, xcode - iphone

I have a Core Data relationship between two entities, which is like this:
Entity A Entity B
aRelationship <-------------->> bRelationship
With the delete rule set to cascade.
Maybe I have this wrong, but I thought that if the delete rule for both of these relationships was set to "Cascade", then when did the following...
[context deleteObject:EntityA];
...it would also delete all the of the Entity B's associated with it. However when I log all of my entity B's it would seem that I am mistaken.
Could someone please shed some light on my confusion?
Thank you very much.

While it's not immediately apparent in the graphical data model editor each recipocal relationship i.e. each
<-->
...is really two separate relationship each with its own delete rule. Delete rules are activate when an object of the entity with the delete rule is deleted.
So, if in the data model editor you have two entities Alpha and Beta with a relationship:
Alpha.betas<-->>Beta.alpha
… then you really have two relationships like so:
Alpha.betas--(delete rule)-->>Beta.alpha
Beta.alpha--(delete rule)-->Alpha.betas
You never want to set up a delete rule like this:
Alpha.betas--(cascade)-->>Beta.alpha
Beta.alpha--(cascade)-->Alpha.betas
… because deleting any one Beta instance will delete the associate Alpha object which will trigger the deletion of all related Beta objects. Depending on the details of your data model, a reciprocal cascade can delete a big chunk of you data by accident.
What you really want is:
Alpha.betas--(cascade)-->>Beta.alpha
Beta.alpha--(nullify)-->Alpha.betas
Now, when you delete the Alpha object, it will delete all associated Beta objects.
When a cascade is blocked, it is usually a problem with a required relationship. Can't tell for certain without details of the data model.

It depends on what delete rules are you using.
Here is what Apple said in their document:
"When you delete a managed object it is important to consider its
relationships and in particular the delete rules specified for the
relationships. If all of a managed object's relationship delete rules
are Nullify, then for that object at least there is no additional work
to do (you may have to consider other objects that were at the
destination of the relationship—if the inverse relationship was either
mandatory or had a lower limit on cardinality, then the destination
object or objects might be in an invalid state). If a relationship
delete rule is Cascade, then deleting one object may result in the
deletion of others. If a rule is Deny, then before you delete an
object you must remove the destination object or objects from the
relationship, otherwise you will get a validation error when you save.
If a delete rule is No Action, then you must ensure that you take
whatever steps are necessary to ensure the integrity of the object
graph."
The link of “Relationship Delete Rules.”: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdRelationships.html#//apple_ref/doc/uid/TP40001857-SW1

Related

CoreData migration - delete rules of relationships

I've found nothing about migration rules in case of changing the deletion rule of a managedObjects relationship
My initial coredata model contained an entity with a relationship. The delete rule of this relationship was cascade. I had to change this behavior to Nullify.
Therefore I've created a new version of my coredata model but without any lightweight migration and it still works. So I wounder if I should have done adding a new version of my model or if the changing the deletion rules (e.g. from cascade to nullify) doesn't effect/need any migration.
Any suggestions?
Deletion rules specify the behavior of Core Data at runtime: If one object is deleted, other relationships may be set to NULL, or related objects may be deleted as well.
Therefore I assumed that the deletion rules are stored only in the Core Data model, but not in the persistent store file.
To verify this, I have created 2 store files from 2 Core Data models with identical entities, but different deletion rules. The NSStoreModelVersionHashes in the persistent stores metadata dictionary were identical.
In fact, both SQLite files were identical with the only exception of the "Z_UUID" in the "Z_METADATA" table, which is the NSStoreUUID of the persistent store file.
Also, addPersistentStoreWithType:... would fail if the version hashes of the loaded store are different from the hashes in the model.
Changing the deletion rules should therefore not be a problem.

JPA/EclipseLink: disable cascade for certain merge operations?

I am using EclipseLink 2.3.3. with a data model with about 100 entities. I have a Java class mapped to each database table using annotations.
I have two use cases to implement. One is that a new record enters the system that hits about 60-75 of the tables. For this case, I want merge and persist to cascade, so that I can just merge the top level object and have that cascade to all related entities.
Another use case is that I need to insert a collection of individual objects, often one from each of a bunch of different tables. In this case I don't want the cascading merge, because I need to have control over the insertions. If I have cascade enabled, merging the first object might or might not merge the other objects, depending on if or how they are related, so I'd rather explicitly merge each of them.
So essentially, I want cascading merge and persist in one situation, but not another. So if I include the cascade annotations in the mapped classes, I need to selectively disable the cascading for certain operations; or, if I turn off cascading in the mapped classes, I would like to enable cascading for certain operations.
So far I am not finding any way to selectively turn on or off cascading for a particular operation. There is a CascadePolicy class but that seems to only be used with queries. There are dynamic entities, and I was thinking perhaps I could use that to do something like create a dynamic entity from an existing entity and turn off the cascading behavior on that entity's relationships and somehow use that for the merge, but I have not been able to find the right API for that.
So I am wondering if there is a better answer somewhere that I'm overlooking? Thanks for any information.
I'm not certain about what level of control you are after, especially in the case that you mention you want to insert individual objects. From the sounds of it, cascade merge is exactly what you want for your Entity object tree in the first case for use with the EntityManager.merge. Merge called on an entity will check if it is new or not, and update or insert as appropriate. Marking relationships as cascade merge will allow finding new objects and having them inserted.
The second case though where you want to handle individual insertions, why not exclude the cascade persist option on mappings and just call EntityManager.persist on the objects you want to insert? Persist then will not cascade, so only the entity you call em.persist on will get inserted. Relationships will be used just to set the foreignkey values - though you might want to leave them nulled out and set them later as part of larger merge calls. Both sides of bidirectional relationships need to be maintained, and if the other side is exists and doesn't get merged, its relationship changes are not stored.
If that isn't what you want, EclipseLink has native API on the UnitOfWork (the EntityManager essentially wraps a UnitOfWork for transactional work) that allows you to specify the merge policy. See mergeClone, deepMergeClone and shallowMergeClone on UnitOfWork, which essentially use CASCADE_ALL_PARTS, CASCADE_PRIVATE_PARTS and NO_CASCADE respectively as the merge policies, while the JPA merges use CASCADE_BY_MAPPING.

Delete object and all its child objects in Entity Framework?

I've been trying to find the answer to this question here. Several people seem to ask similar things, but I don't get the answers. I have an EF entity with a bunch of child entities (one-to-many relationship). I want to be able to delete the "parent" entity and have all the child entities deleted at the same time.
Some people mention "Cascade Delete" should be set on both EF model and database (Sql Server in my case). The problem is:
I have absolutely no idea how to do this (seems to be implied in those answers that you should know, but sorry...)
I have a feeling I've run into a similar problems before and found an answer somewhere that was simpler than setting this Cascade Delete. I may be wrong, maybe it is the only way, but if there is a simpler solution I'd like to know.
In either case, a clear example of how to get this working would be greatly appreciated!
In SQL Managment Studio go to your database and find the table where there should be a foreign key. Add a foreign key to the table pointing to the other table. I assume you know how to setup a foreign key. In the foreign key setup at the bottom of the dialog window you'll see a Delete property. Set it to Cascade. This will cause any dependent rows to be deleted whenever the parent row is deleted. Then go and update your data model in Visual Studio. Everything should be setup for you now.
Here is some relevant documentation on MSDN. Note though that there appears to be an error in the example. I received the following error from the EDMX designer when using this configuration.
Operations cannot be specified on ends with multiplicity '*'.
You should set the OnDelete property to Cascade for the end will be triggering deletes on the other end.
As an example, in a relationship involving customers and orders where you would like to have a customer's orders deleted along with the customer, you should set the OnDelete property for the Customer role to Cascade.
Note that only objects that have been loaded into the ObjectContext will be affected by a cascading delete. You will be relying on the cascading delete that you set in the database to look after any other records.

Many-to-many relationship constrains in Core Data

I have entities Word and Tag. Both have To-Many relationship to each other, as well as inverse. The way I need to constrain it that:
if I delete a Word then only the related Tags which has no Word pointing to them will be deleted
if I delete a Tag which has Words pointing to it then just nullify those set items.
Is it possible to model?
This is something that needs to be handled in code. You need to create custom subclasses for your Word and Tag entities and implement the -prepareForDeletion method in each. Then you can check the logic and handle it appropriately. I would also set the delete rule for the relationships between the entities as deny

When my relationship delete rule is set to Nullify, will the inverse relationship also be deleted?

Example: I have a Department and an Employee. Department has a Nullify relationship to many Employees, and an Employee has an inverse relationship to one Department.
Now I remove the relationship to an Employee. So lets say the Marketing Department doesn't link anymore to Joe Stevens.
1) Does Joe Stevens still link to the Marketing Department, when asking for his Department? Or is Core Data handling this automatically and also "nullifying" that?
2) Does it matter which delete rule is specified on the side of the Employee? Let's say that was Cascade. The Department removed the relationship to the Employee. I believe the delete rule of the Employee is not relevant in this case, right?
The delete rule govern what happens to the object at the other end of the relationship when the object holding the rule itself is deleted.
So:
A<-(cascade)->>B
B<<-(nullify)->A
Deleting A causes the deletion of all related B. However, deleting any single one B simply causes A to forget about that particular B.
So, the delete rule is always relevant to the object it is targeted at because the targeted object is the entire point of the delete rule. This is especially true when objects have multiple relationships.
A<-(cascade)->>B
B<<-(nullify)->A
C<--(cascade,required)-->>B
The C object will block the cascade deletion of any B objects it also holds regardless of what A wants. (A will nullify in that case.)
You should not think of delete rules in terms of actual programming but rather in terms of the real world system you are trying to model. Think about the relationship of the real system and then set the delete rules to mimic those. In this case we would mimic the actually organizational rules of the company.