【问题标题】:iPhone Core Data: Cascading delete across a many-to-one relationshipiPhone Core Data:跨多对一关系的级联删除
【发布时间】:2011-01-13 07:59:33
【问题描述】:

我有两个类 A 和 B,从 A 到 B 具有多对一的关系(多个 A 对象可能引用同一个 B)。问题是,如果A端的删除规则是Cascade,那么B只有在last引用A被删除时才会被删除,还是会在第一次时被删除关联的 A 被删除。如果重要,关系 B 方的删除规则是 Nullify。

另外,我在 Core Data 文档中读到 Optional 标志在某些情况下很重要。但不清楚他们所说明的关系与我的案件有何关系。他们在谈论一个遏制案例(B 归 A 所有),而我的案例是订阅/关联之一(B 与 A 有关)。

我可以简单地在代码中以编程方式管理删除,但如果可能的话,我希望允许 Core Data 做正确的事情。但目前尚不清楚我正在寻找的垃圾回收语义是否在 Core Data 中得到支持。

有什么建议吗?

【问题讨论】:

    标签: iphone cocoa cocoa-touch core-data cascading-deletes


    【解决方案1】:

    我的目标显然与您相同(删除最后一个引用的 A 后立即删除 B)。我花了比预期更长的时间才能做到这一点。特别是因为

    • A准备删除的时候,B中的一对多关系可能还没有更新,所以不能只计算A B中引用。
    • isDeleted on A 似乎已在 -prepareForDeletion 期间设置

    如果有人感兴趣,这对我有用(我会使用 Department > Employee 因为它更容易阅读):

    员工中:

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

    其他人建议将此逻辑放入部门中的-willSave。我更喜欢上面的解决方案,因为在某些情况下(例如,在手动存储迁移或数据导入期间)我可能真的想保存一个空部门。

    【讨论】:

    • 只是一个建议...由于文档没有说不需要向 super 发送消息,因此这样做可能是个好主意:[super prepareForDeletion]
    【解决方案2】:

    这是 Lukas 回答的 Swift 4 版本:

    public override func prepareForDeletion() {
        guard let department = department else { return }
    
        if department.employees.filter({ !$0.isDeleted }).isEmpty {
            managedObjectContext?.delete(department)
        }
    }
    

    【讨论】:

      【解决方案3】:

      添加到@JanApotheker 答案,您还需要保存 managedObjectContext 并将过滤器的参数转换为 AnyObject,因为它像这样遍历 NSSet:-

      public override func prepareForDeletion() {
          guard let department = department, let employees = department.employees else { return }
      
          if employees.filter({ !($0 as AnyObject).isDeleted }).isEmpty {
              managedObjectContext?.delete(department)
              do {
                  try managedObjectContext?.save()
              } catch {
                  
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-01-20
        • 2017-06-02
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        • 2020-07-27
        • 1970-01-01
        • 2012-03-31
        • 2016-01-17
        相关资源
        最近更新 更多