I just want to check really quickly. Say I have two entities in a data model: Catalog, and Product. They have a many-to-many relationship with each other, and both are required (a Catalog must have at least one Product, and all Products must each belong to at least one Catalog). So if I was to delete a Product, its deletion should be Nullify, of course.
But what should the deletion policy be for Catalog? If a Catalog is deleted, not all of its Products necessarily exclusively belong to it. A Product may belong to more than one Catalog. So I definitely shouldn't use Cascade. However, is Nullify sufficient? What if I end up with dangling Products that don't belong to a Catalog? What does Core Data have built in that would resolve this issue with many-to-many schemas? Do I need to modify my schema?
Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.
In the INSERT and UPDATE specifications, select Cascade for the delete rule. Click on Close and save the table in the designer. Click Yes in the warning message window. Once you click on Yes, a foreign key with delete rule is created.
Nullify is sufficient, and many-to-many sounds right. The specific constraint you want (deleting orphans) is not directly enforceable by core data, though, so you get to do a little cleanup yourself.
Specifically, implement willSave
in your entity classes, and have each entity test: am I not deleted; and, do I have no associated (products/catalogs)? If so, delete myself. (the not-deleted test is important to avoid an infinite loop of willSave
s.)
This postpones the deletion of the orphaned catalogs or products until save time. This is probably not a problem.
I've implemented rgeorge's answer, and thought the exact code might be helpful to other people:
- (void)willSave { [super willSave]; if (self.isDeleted) return; if (self.products.count == 0) [self.managedObjectContext deleteObject:self]; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With