假设我有一个自定义的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];
这样的代码将起作用。但是,这在我已经相应设置删除规则的非常简单的项目中不起作用。
由于
答案 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