2010-02-04 6 views
20

J'ai deux classes A et B avec une relation plusieurs-à-un de A à B (plusieurs objets A peuvent faire référence au même B). La question est, si la règle de suppression sur le côté A est Cascade, B sera supprimé seulement lorsque le dernier référençant A est supprimé ou sera-t-il supprimé le premier temps un A associé est supprimé. La règle de suppression pour le côté B de la relation est Nullify si cela est important.iPhone Core Data: Suppression en cascade dans une relation plusieurs-à-un

En outre, j'ai lu dans les documents de base de données que l'indicateur facultatif est important dans certains cas. Mais il n'était pas clair comment les relations qu'ils illustraient se rapportaient à mon cas. Ils parlaient d'un cas de confinement (B appartient à A) alors que mon cas est celui d'un abonnement/association (B est lié à A).

Je pouvais simplement gérer la suppression programmatique dans le code mais je voulais permettre aux Core Data de faire ce qu'il fallait, si possible. Mais il n'est pas clair que la sémantique de récupération de place que je recherche est prise en charge dans les données de base.

Des suggestions?

Répondre

14

J'ai eu le même but que vous aviez apparemment (supprimer B dès que le dernier référencé A est supprimé). Il m'a fallu plus de temps que prévu pour bien faire les choses. En particulier parce que

  • Au moment Un prépare pour la suppression, l'à-plusieurs dans B pourrait ne pas être encore mis à jour, de sorte que vous ne pouvez pas compter seulement la A référencées dans B.
  • isDeleted sur Un semble déjà défini lors -prepareForDeletion

Voici ce qui a fonctionné pour moi si quelqu'un est intéressé (je vais utiliser Département < - >>employés parce qu'il est plus facile à lire):

En employé:

- (void)prepareForDeletion { 
    // Delete our department if we we're the last employee associated with it. 
    Department *department = self.department; 
    if (department && (department.isDeleted == NO)) { 
     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isDeleted == NO"]; 
     NSSet *employees = [department.employees filteredSetUsingPredicate:predicate]; 

     if ([employees count] == 0) {   
      [self.managedObjectContext deleteObject:department]; 
     } 
    } 
} 

D'autres personnes ont suggéré de mettre cette logique dans -willSave dans Département. Je préfère la solution ci-dessus étant donné que je souhaiterais peut-être enregistrer un département vide dans certains cas (par exemple, lors de la migration d'un magasin manuel ou de l'importation de données).

+0

Juste une suggestion ... Étant donné que les documents ne disent pas qu'il est pas nécessaire de super message, il est probablement une bonne idée de faire donc: [super prepareForDeletion] –

0

Voici une la version Swift 4 de la réponse de Lukas:

public override func prepareForDeletion() { 
    guard let department = department else { return } 

    if department.employees.filter({ !$0.isDeleted }).isEmpty { 
     managedObjectContext?.delete(department) 
    } 
} 
Questions connexes