【问题标题】:Core Data delete rule -- to-many relationship, delete when emptyCore Data 删除规则——多对多关系,空时删除
【发布时间】:2012-03-31 06:24:20
【问题描述】:

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

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

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

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

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

  • Core Data 是否有办法至少自动执行其中一些操作,例如关系删除规则?
  • 是否有一种“规范”的首选方法来处理这种情况?

【问题讨论】:

    标签: objective-c core-data


    【解决方案1】:

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

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

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

    【讨论】:

    • 除非发生其他事情,否则在同时删除作者的两本书的情况下,这似乎会失败。我在相应的 prepareForDeletion 中打印出 author.books.count 的值,两本书的值都是 2。然后作者永远不会被删除。 (类名已更改以匹配问题,但关系相同。)
    【解决方案2】:

    瑞克斯特,

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

    1. 作者 -- (拒绝) -->> 书籍

    不允许删除图书关系非空的作者

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

    1. 书--(级联)-->作者

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

    您不能删除作者,正如我们的第一条规则所说,如果有任何非空书籍不应删除。如果它们不存在,则作者将被删除。

    我认为理论上它应该有效。让我知道,这是否有效。

    【讨论】:

    • Author -(Deny)->> Books 很好,但Book -(Cascade)-> Author 会导致作者在该作者的第一本书被删除后立即被删除。 (要么那个,要么我做错了什么。)
    • 但是同一个作者绑定了DENY关系权,所以理论上不会被删除,因为他还有一本书。
    【解决方案3】:

    与 Tim 的解决方案类似,您可以覆盖 Author NSManagedObject 子类中的 willSave 方法。请注意,如果您确实使用了 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];
    }
    

    【讨论】:

      【解决方案4】:

      以下内容对我有用:

      将您的作者实体的“书”关系的删除规则设置为“拒绝”,这意味着只要有一本书与您的作者关联,就不能删除它。

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

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

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

      【讨论】:

        猜你喜欢
        • 2012-04-15
        • 2011-09-29
        • 1970-01-01
        • 2021-03-30
        • 2011-01-13
        • 1970-01-01
        • 2011-01-20
        • 2020-09-12
        • 1970-01-01
        相关资源
        最近更新 更多