it-swarm.com.de

Wie lösche ich alle Objekte über eine Kerndatenbeziehung?

Angenommen, ich habe ein benutzerdefiniertes NSManagedObject Department und dieses hat eine Eigenschaft, die eine Beziehung zu vielen Mitarbeitern darstellt, d. H. NSSet *employees;.

Für eine bestimmte Abteilung möchte ich alle Objekte in Mitarbeitern entfernen. Was ist der empfohlene/beste Weg, dies zu tun?

Hypothetisch würde mein Code also so aussehen:

Abteilung.h

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

Abteilung.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."

Die Beziehung employees ist nicht optional, daher schätze ich, dass das Entfernen von Mitarbeitern aus der Abteilung bedeutet, dass ich versuche, die Mitarbeiter "zu verwaisen", d. H. Die Mitarbeiter im beständigen Modell ohne zugeordnete Abteilung zu belassen.

Ich denke also, meine ursprüngliche Frage sollte umformuliert werden auf: Was ist der beste/empfohlene Weg, um alle "Kind" -Objekte eines "Elternteils" zu entfernen, wenn die Kinder eine nicht-optionale Beziehung zum Elternteil haben?

Ich vermute, dass die Antwort "Schleife durch und löschen Sie die Mitarbeiter Objekte nacheinander" sein wird.

UPDATE

Laut einer Antwort und einem Link zu Apples Dokumentation sollte es mir möglich sein, die Löschregel auf "Cascade" zu setzen und dann funktioniert Code wie department.employees = [NSSet set];. Dies funktioniert jedoch nicht in meinem sehr einfachen Projekt, in dem ich die Löschregel entsprechend eingestellt habe.

Vielen Dank

19
stifin

Wenn Sie die Mitarbeiterelemente für eine bestimmte Abteilung löschen möchten, können Sie eine For-In-Schleife wie für ausführen

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

Speichern Sie dann Ihren verwalteten Kontext. WENN Sie das natürlich wollen und nicht die Beziehung zwischen Mitarbeitern und Abteilung aufheben; In diesem Fall würde das Zuweisen eines leeren Sets funktionieren.

Variation über oben:

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

Durch Festlegen der Mitarbeiterbeziehung der Abteilung auf eine leere Gruppe werden die Mitarbeiter unabhängig von der Löschregel NICHT gelöscht. Ich glaube, Sie verstehen die Löschregel falsch. In den Apple-Dokumenten heißt es: "Die Löschregel einer Beziehung gibt an, was passieren soll, wenn versucht wird, das Quellobjekt zu löschen." Eine Kaskadierung wird daher nur wirksam, wenn wir die Abteilung LÖSCHEN. Indem wir die Beziehung zu einer leeren Gruppe festlegen, trennen wir nur die Mitarbeiter von der Abteilung und löschen sie nicht. Wenn diese Beziehung für die Mitarbeiter nicht als optional festgelegt ist, wird beim Speichern ein Fehler verursacht. Wenn Sie die Mitarbeiter aus der Abteilung löschen möchten, können Sie sie wie oben aufgeführt durchlaufen oder die Abteilungsbeziehung so einstellen, dass sie kaskadiert und anschließend die Abteilung gelöscht wird.

15
Scott Pfeil

Ich hatte auch so etwas wie unten, aber es hat nicht funktioniert ...

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

}

Offensichtlich kann die Datenbankebene die Sounds und dann die Sammlung nicht auf einmal löschen. Das Setzen der Löschregel für die Beziehung 'Kaskade' hat mein Problem gut gelöst und ich verwende einfach:

[context deleteObject:collection];

Wenn Sie einigen Leuten detaillierte Lesezeiten ersparen möchten, markieren Sie dies einfach als Antwort.

Wie Fervus bereits sagte, kann dieser Link auch für die Profis hilfreich sein: Löschungen sofort in Core Data verbreiten

1
DynamicDan