我可以在具有删除规则的关系的实体上使用 NSBatchDeleteRequest 吗?

问题描述 投票:0回答:3

我正在尝试使用 NSBatchDeleteRequest 删除一堆实体,其中许多实体具有删除级联和/或无效规则。

我第一次尝试删除任何内容都失败了,我返回的 NSError 包含字符串“批量删除不支持删除规则”。我原以为删除这些东西没问题,但我有责任确保在保存之前满足所有约束条件。

是否可以批量删除这些托管对象? (我想保留删除规则,其他删除路径没有简单的方法知道要删除哪些对象集)在这种情况下,某些类型的批量删除是否有效,但其他类型的无效? (假设谓词失败,但对象 ID 列表有效?)

core-data
3个回答
8
投票

批量删除关系有问题。

直接进入数据库,删除暂停所有对象图规则的记录,包括删除规则。您已经正确地确定了您需要自己再次进行所有约束检查的要求。 (这本身可能会破坏交易。)

即使您设法正确删除了实体和所有必要的相关实体,您仍然会在(不透明的)join table Core Data 在后台创建的表中留下很多条目。没有明显的安全方法来删除连接表中的条目,并且据报道它们会干扰未来操作中的关系管理。

IMO,这种情况下的解决方案是仍然使用对象图而不是批量删除和性能优化。 SOF 上有很多关于如何做到这一点的很好的答案,但大部分可以总结为以下几点:

  • 找到合适的批量大小进行保存(通常创建 500 个实体,删除约 2000 个实体,但这可能因对象大小和关系复杂性而异——您必须进行试验)。
  • 如果您有内存限制,请使用
    autoreleasepool
    s。
  • 使用背景上下文释放 UI 以进行交互。我更喜欢在更新 UI 后在后台保存到数据库。

1
投票

刚刚写了一个简单的Department-Employee(一对多)demo工程。

Empolyee
department
关系的删除规则设置为
cascade
.

使用批量删除删除一个

department
和两个
employees
时,删除的对象数量只有1。所以暂时,批量删除无视删除规则.

您可以自己尝试一下:

func deleteDepartment(named name: String) {
    let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Department")

    fetch.predicate = NSPredicate(format: "name = %@", name)

    let req = NSBatchDeleteRequest(fetchRequest: fetch)

    req.resultType = .resultTypeCount

    do {
        let result = try self.persistentContainer.viewContext.execute(req)
                            as? NSBatchDeleteResult

        print(result?.result as! Int)   // number of objects deleted

    } catch {
        fatalError("Error!!!!")
    }
}

0
投票

如果有人需要这个: 您可以为父实体和子实体使用两个

NSBatchDeleteRequest

    let childFetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "ChildEntityName")
    let childDeleteRequest = NSBatchDeleteRequest(fetchRequest: childFetchRequest)
    do {
        try persistenceService.context().execute(childDeleteRequest)
        let parentFetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "ParentEntityName")
        let parentDeleteRequest = NSBatchDeleteRequest(fetchRequest: parentFetchRequest)
        
        try persistenceService.context().execute(parentDeleteRequest)
        persistenceService.saveContext()
    }catch {
        persistenceService.context().reset()
        /// handle error
    }
© www.soinside.com 2019 - 2024. All rights reserved.