Подтвердить что ты не робот

Как удалить все объекты через взаимосвязь данных ядра?

Скажем, у меня есть пользовательский 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

В соответствии с ответом и ссылкой на документацию Apple, я должен установить правило удаления для "Cascade", а затем код, как department.employees = [NSSet set];, будет работать. Однако это не работает в моем очень простом проекте, где я правильно установил правило удаления.

Спасибо

4b9b3361

Ответ 1

Если вы хотите удалить элементы сотрудника для определенного отдела, вы можете запустить цикл 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];
}

Ответ 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];

Если вы хотите сохранить некоторое время для детального просмотра, просто отметьте это как ответ.

Как сказал Фервус выше, эта ссылка также может быть полезна для профи: Пропагандировать удаление сразу в Core Data