核心数据删除规则 - 多对多关系,空时删除

时间:2012-03-14 18:32:57

标签: objective-c core-data

我对Core Data中关系的删除规则如何工作有点模糊,至少超出了文档中描述的简单情况。

大多数情况,以及我在这里看到的问题的大多数答案都使用了一个模型,其中一对多关系左侧的对象“拥有”右侧的对象:例如PersonPhoneNumber个,如果删除该人,则删除所有关联的号码。在这种情况下,解决方案很明确:如果您设置如此关系,Core Data将为您处理所有事情:

Person      --(cascade)-->> PhoneNumber
PhoneNumber --(nullify)-->  Person

我感兴趣的是相反的情况:“所有权”相反的多对多关系。例如,我可能会扩展CoreDataBooks示例代码以添加Author实体,以便在一个位置收集有关唯一作者的所有信息。 Book有一位作者,但作者有很多书......但我们并不关心我们没有列出书籍的作者。因此,不应允许删除Author关系非空的books,删除引用特定Book的最后Author应该删除Author

我可以想象手动执行此操作的几种方法......我不确定的是:

  • 与关系删除规则一样,核心数据是否至少可以自动执行其中一些操作?
  • 是否存在处理此类情况的“规范”,首选方式?

4 个答案:

答案 0 :(得分:14)

您可以覆盖prepareForDeletion课程中的Book,并检查作者是否还有其他书籍。如果没有,你可以删除作者。

- (void)prepareForDeletion {
    Author *author = self.author;
    if (author.books.count == 1) { // only the book itself
        [self.managedObjectContext deleteObject:author];
    }
}

编辑:为了防止删除带书籍的作者,您可以覆盖validateForDelete甚至更好:不要首先使用带书籍的作者调用deleteObject

答案 1 :(得分:2)

Rickstr,

检查以下关系以完成两个标准。

  1.   

    作者 - (拒绝) - >>图书

  2. 删除不应允许其图书关系非空的作者

      

    DENY:如果关系目标中至少有一个对象,则无法删除源对象。

    1.   

      书 - (级联) - >作者

    2. 删除引用特定作者的最后一本书应删除该作者

      您不能删除作者,因为我们的第一条规则是,如果有任何非空的书籍不应删除。如果它们不存在则会删除作者。

      我认为理论上应该有效。如果这有效,请告诉我。

答案 2 :(得分:1)

与Tim的解决方案类似,您可以覆盖作者willSave子类中的NSManagedObject方法。请注意,如果您使用Tim的解决方案,我强烈建议您过滤为尚未删除的图书设置的图书;这样,如果您同时删除所有作者的书籍,作者仍将被删除。

- (void)willSave {
    if (!self.isDeleted) {
        NSPredicate *notDeletedPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary<NSString *,id> *bindings) {
            return ![(NSManagedObject *)evaluatedObject isDeleted];
        }];
        NSSet *filteredBooks = [self.books filteredSetUsingPredicate:notDeletedPredicate];
        if (filteredBooks.count == 0)
            [self.managedObjectContext deleteObject:self];
    }
    [super willSave];
}

答案 3 :(得分:0)

以下内容对我有用:

将您的作者实体的“书”关系上的删除规则设置为“拒绝”,这意味着只要有一本书链接到您的作者,就无法删除。

子类化您的图书实体,并按如下所示重写prepareForDeletion()函数:

public override func prepareForDeletion() {
    super.prepareForDeletion()
    do {
        try author.validateForDelete()
        managedObjectContext?.delete(author)
    } catch {}
}

除非书本关系为空,否则验证删除将引发错误。 您可以选择处理错误。