【问题标题】:How to delete all objects through a core data relationship?如何通过核心数据关系删除所有对象?
【发布时间】:2011-09-13 04:46:31
【问题描述】:

假设我有一个自定义 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 文档的链接,我应该能够将删除规则设置为“级联”,然后像 department.employees = [NSSet set]; 这样的代码将起作用。但是,这在我已相应设置删除规则的非常简单的项目中不起作用。

谢谢

【问题讨论】:

  • 我想知道您是否找到了解决该问题的方法?我有同样的问题..坚持你的例子我有一个同步过程,我试图删除所有员工,然后从头开始创建它们(不要让我的同步太复杂)..但目前唯一的方法我得到的工作是消除双方的“多”关系 - 迭代调用 [managedObjectContext deleteObject:employee] 的员工,然后执行 [[department mutableSetValueForKey:@"employees"] removeAllObjects];这似乎是错误的,但有效..
  • 我从来没有让上面的例子工作。最后,我遍历了员工并删除了他们,如下面的回复中我刚刚接受了答案
  • 您误解了文档。当您删除部门对象时,删除规则将应用于员工集中的员工对象。更改关系不会删除任何对象。

标签: objective-c cocoa macos core-data


【解决方案1】:

如果要删除特定部门的员工元素,则可以运行 for-in 循环,例如 for

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

然后保存您的托管上下文。如果那当然是你想要的,而不是消除员工与部门之间的关系;在这种情况下,分配一个空集就可以了。

上面的变化:

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

【讨论】:

  • 只是将循环的指针theEmployee设置为nil,它根本不会影响托管对象。
  • 目前,这是我使用的技术,只是因为我无法使级联删除工作......除了我的更简单。我已将其粘贴在您的代码下方
  • 感谢分享!我使用了 objectWithID 技术,因为我会通过直接删除对象偶尔出现异常,但我认为您的方法在您的程序上下文中是有意义的。 (如果您满意,请随意批准答案)。
  • 它“有用”,因为这是我正在使用的代码,但它也是我不想使用的代码,因为我觉得级联删除方法应该是这种方式去(否则,为什么那个选项甚至在那里?)......我只是不明白为什么级联删除对我不起作用。有没有人在stackoverflow中发布过实际代码或整个项目?如果他们有实际的项目,我相信有人会立即发现问题
【解决方案2】:

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

【讨论】:

  • 谢谢——您的回答触及了问题的根源,并证实了我怀疑删除规则是如何起作用的。我认为如果您添加一些代码,它将成为(当然应该)首选答案。
【解决方案3】:

我也有类似下面的东西,但它没有用......

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    相关资源
    最近更新 更多