Say you have departments and employees and each department has several employees, but each employee can also be part of several departments.
So there is a many-to-many relationship between employees and departments. When deleting a department I would like to delete all employees that are only part of that department and nullify the relationship to this department for all employees that are also member of another department.
Would a cascade-rule in both directions do that? Or does a cascade rule automatically delete all employees of a department regardless of other affiliations?
Setting the Delete Rule to Protect prevents deleting records of the main Entity while there are associated records in the related Entity. This behavior is ensured by a database constraint created on the reference attribute.
Inverse relationships enable Core Data to propagate change in both directions when an instance of either the source or destination type changes. Every relationship must have an inverse. When creating relationships in the Graph editor, you add inverse relationships between entities in a single step.
Overview. Core Data provides a set of classes that collaboratively support your app's model layer: An instance of NSManagedObjectModel describes your app's types, including their properties and relationships. An instance of NSManagedObjectContext tracks changes to instances of your app's types.
A cascade rule will automatically delete the objects at the destination. So, if you delete a department, the employees will be deleted regardless of the number of departments they're in.
It sounds like the behavior you want is a little more nuanced, to delete only the "orphaned" employees -- i.e. those that don't have a department. When you delete a department, a good way of finding those would be to do something like this:
NSManagedObject *doomedDepartment = // get the department to be deleted
NSSet *employees = [doomedDepartment valueForKey:@"employees"];
NSSet *orphanedEmployees = [employees filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"departments.@count == 1"]];
for (NSManagedObject *orphanedEmployee in orphanedEmployees) {
[managedObjectContext deleteObject:orphanedEmployee];
}
[managedObjectContext deleteObject:doomedDepartment];
Thanks, alex. I will probably do that. In the meantime I had found a different way of doing this:
1.) register for notifications on changes:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(managedObjectContextDidChange:)
name:NSManagedObjectContextObjectsDidChangeNotification
object:managedObjectContext];
2.) when changes occur and an employee gets updated. I check if that object has 0 relations to departments and delete it:
- (void)managedObjectContextDidChange:(NSNotification *)notification {
NSSet *updatedObjects = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
for(NSManagedObject *obj in updatedObjects){
// walk through updated objects -> check for employees
// check if they still contain departments and if not delete them
if([obj.entity.name isEqualToString:@"Employee"]){
NSLog(@"Employee changed!");
if([[(Employee*)obj Departments] count]==0){
NSLog(@"No more relations -> Delete Employee");
[managedObjectContext deleteObject:obj];
}
}
}}
That works well too, but might get more complicated if you have several different entities for which to observe this kind of behavior.
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