如何通过核心数据关系删除所有对象?

时间:2011-06-11 21:15:01

标签: objective-c cocoa macos core-data

假设我有一个自定义的NSManagedObject Department,它有一个表示与员工的多对多关系的属性,即NSSet *employees;

对于给定的部门,我想删除员工中的所有对象。请问有什么建议/最好的方法吗?

因此,假设我的代码看起来像这样:

Department.h

@interface Department: NSManagedObject {
}
@property (retain) NSString *departmentName;
@property (retain) NSSet *employees;
@end

Department.m

@implementation Department
@dynamic departmentName;
@dynamic employees;

Employee.h

@interface Employee: NSManagedObject {
}
@property (retain) NSString *firstName;
@property (retain) NSString *lastName;
@property (retain) Department *worksIn;
@end

doCoreDataStuff

- (void)doCoreDataStuff:sender {
    //add a department, give it a couple employees, then try to remove those employees
    NSEntityDescription *deptEntity = [NSEntityDescription entityForName:@"Department"
                                                 inManagedObjectContext:self.managedObjectContext];
    Department *dept = [Department alloc] initWithEntity:deptEntity
                          insertIntoManagedObjectContext:self.managedObjectContext];
    NSError *error;

    dept.departmentName = @"Accounting";
    //save more often than normal to see more easily what causes error
    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]);

    NSEntityDescription *empEntity = [NSEntityDescription entityForName:@"Employee"
                                                 inManagedObjectContext:self.managedObjectContext];
    emp.firstName = @"Steve";
    emp.lastName = @"Smith";
    emp.worksIn = dept;

    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]);

    emp = [[Employee alloc] initWithEntity:empEntity
            insertIntoManagedObjectContext:self.managedObjectContext];
    emp.firstName = @"Natasha";
    emp.lastName = @"Johnson";
    emp.worksIn = dept;

    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]);

    //all good so far! now will try to delete all employees for this department
    dept.employees = [NSSet set];
    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]); //"Multiple validation errors occurred."

    //this also produces the same error
    [[dept mutableSetValueForKey:@"employees"] removeAllObjects];
    if (![self.managedObjectContext save:&error]) NSLog(@"\nError: %@", [error localizedDescription]); //"Multiple validation errors occurred."

关系employees不是可选的,因此我猜测从部门中删除员工意味着我正在尝试“孤儿”员工,即将员工留在持久模型中而没有相关部门。

所以,我认为我原来的问题应该改写为:当孩子与父母有非选择性关系时,删除“父母”的所有“子”对象的最佳/推荐方法是什么?

我怀疑答案是“循环并一次删除一个员工对象”。

更新

根据Apple的文档的答案和链接,我应该能够将删除规则设置为“Cascade”,然后像department.employees = [NSSet set];这样的代码将起作用。但是,这在我已经相应设置删除规则的非常简单的项目中不起作用。

由于

3 个答案:

答案 0 :(得分:16)

如果要删除特定部门的员工元素,则可以像

一样运行for-in循环
for (Employees * theEmployee in department.employees) {
  [self.managedObjectContext deleteObject:[self.managedObjectContext objectWithID:theEmployee.objectID]]; 
}

然后保存您的托管上下文。如果这是你想要的,而不是消除员工和部门之间的关系;在这种情况下,分配一个空集将起作用。

上面的变化:

for (Employee *employeeToDelete in department.employees) {
    [self.managedObjectContext deleteObject:employeeToDelete];
}

答案 1 :(得分:16)

将部门的员工关系设置为空集不会删除员工,无论删除规则如何。我相信你误解了删除规则。根据苹果文档: “关系的删除规则指定了在尝试删除源对象时应该发生的事情”。 因此,级联只有在我们删除部门时才会生效。通过将关系设置为空集,我们所做的只是将员工与部门分开,而不是删除它们。如果员工的关系未设置为可选,则在保存时会导致错误。如果要从部门中删除员工,可以按上面列出的方式对其进行迭代,或者将部门关系设置为级联,然后删除部门。

答案 2 :(得分:1)

我也有类似下面的东西,但它不起作用......

- (BOOL)deleteCollection:(Collection *)collection
{
// Grab the context
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;

[collection removeSounds:collection.sounds];
[context deleteObject:collection];

// Save everything
if ([context save:&error]) {
    return YES;
}
return NO;

}

显然,数据库层无法立即删除声音然后删除集合。 将关系设置为“级联”的删除规则很好地解决了我的问题,让我使用:

[context deleteObject:collection];

如果你想节省一些人的详细阅读时间,那就把它标记为答案。

正如Fervus所说,这个链接也可能对专业人士有所帮助: Propagate deletes immediately in Core Data