views:

253

answers:

2

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?

+3  A: 

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];
Alex
+2  A: 

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 OSMObjects 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.

Felix
If you are working on Cocoa Touch or Snow Leopard, you can put this logic in the department's `-prepareForDeletion` method.
Marcus S. Zarra
i think this is a better solution, thanks!
Nick