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

问题描述:

假设我有一个自定义的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是不可选的,所以我猜测,从部门员工删除意味着,我想“孤儿”的员工,即员工保持在坚持没有相关部门的模型。

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

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

UPDATE

根据答案,苹果的文档的链接,我应该能够设置删除规则“瀑布”,然后像department.employees = [NSSet set];代码将工作。但是,这在我非常简单的项目中无效,因为我已经相应地设置了删除规则。

感谢

+1

我不知道,如果你已经找到了解决这一问题?我有同样的问题..坚持你的例子我有一个同步过程中,我试图删除所有员工,然后从头开始创建它们(不要让我的同步过于复杂)..但目前唯一的方法我得到这个工作就是去掉双方的'to many'关系 - 迭代员工调用[managedObjectContext deleteObject:employee],然后执行[[department mutableSetValueForKey:@“employees”] removeAllObjects];这似乎是错误的,但工程.. – herbert 2011-11-05 11:32:09

+0

我从来没有得到上面的例子工作。最后,我重复了员工并删除了他们,如下面我刚刚接受的答复 – stifin 2011-11-13 13:58:00

+3

您误解了文档。删除部门对象时,删除规则将应用于员工集中的员工对象。改变关系不会删除任何对象。 – Eric 2012-05-09 20:21:04

如果你想删除员工元素特定部门,那么你就可以运行了,在像

for (Employees * theEmployee in department.employees) { 
    [self.managedObjectContext deleteObject:[self.managedObjectContext objectWithID:theEmployee.objectID]]; 
} 

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

变化上面:

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

只是将循环的指针'theEmployee'设置为零,它根本不会影响管理对象。 – 2011-06-11 21:56:36

+0

我的不好,编辑;) – 2011-06-12 00:31:17

+0

目前,这是我使用的技术,因为我不能让级联删除工作...除了我的更简单。我已将它粘贴到您的代码下面 – stifin 2011-06-13 14:49:23

设置为空集该部门的雇员的关系将不会删除员工,无论是删除规则的。我相信你误解了删除规则。根据苹果文档: “关系的删除规则指定如果尝试删除源对象应该发生的情况”。 因此,级联只会在我们删除部门时生效。通过将关系设置为空集,我们所做的就是将员工与部门分离,而不是将其删除。如果员工没有将这种关系设置为可选,这将在保存时导致错误。如果您想从部门中删除员工,则可以按照上面列出的方法遍历他们,或者将部门关系设置为级联,然后删除部门。

+0

谢谢 - 你的答案到了问题的根源,并确认我是如何怀疑删除规则的工作。我想如果你添加了一些代码,它会成为(当然应该)首选的答案。 – Benjohn 2017-05-12 11:37:00

我也有过类似下面,但它没有工作...

- (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