【问题标题】:Establishing to-many relationships between NSManagedObjects created in a NSBatchInsertRequest在 NSBatchInsertRequest 中创建的 NSManagedObjects 之间建立一对多关系
【发布时间】:2021-06-25 23:45:44
【问题描述】:

在我的示例应用程序中,CDStory 具有一对一关系 source,它将 one CDStory 映射到 one CDNewsSource

此外,CDNewsSource 具有一对多关系 story,它将 一个 CDNewsSource 映射到 一个或多个 CDStory 实例。

当然,source 的倒数是story

当我创建一个CDStory 实例时,我想立即设置它应该映射到的CDNewsSource。但是,当我在批量插入请求中执行此操作时,我收到有关不同上下文的错误,即使看起来我添加 CDNewsSource 的上下文应该与 CDStory 的上下文匹配。*

代码

let context = container.newBackgroundContext()
context.performAndWait { /* Thread 3: "Illegal attempt to establish a relationship 'source' between objects in different contexts... */
    let total = items.count
    var i = 0
    let batchInsert = NSBatchInsertRequest(entity: CDStory.entity(), managedObjectHandler: { managedObject in
        guard i < total else { return true }
        defer { i += 1 }
        let story = managedObject as! CDStory
        let item = items[i]
        story.title = item.title
        let source = CDNewsSource(context: context)
        managedStoryObject.source = source /* Establishing relationship here. */
        return false
    })
    try! context.execute(batchInsert)
}

*从错误日志中,我确实看到执行上下文是NSSQLBatchInsertRequestContext,这可能与NSBatchInsertRequestmanagedObjectHandler 中使用的背景上下文不同。不清楚这是怎么回事,因为我在执行和创建批量插入请求时指定了上下文。

完整的错误日志

CoreData: error: SQLCore dispatchRequest: exception handling request
<NSSQLBatchInsertRequestContext: 0x6000014fe8e0> , Illegal attempt to establish a relationship 'source' between objects in different contexts
  (source = <CDStory: 0x6000013c0ff0> (entity: CDStory; id: 0x600003098e00 <x-coredata:///CDStory/tAEF068C8-35C0-4287-8F13-84D6B5B35A6D2>; data: {
      title = "Example Story Title";
      source = nil;
  }) , destination = <CDNewsSource: 0x6000013c37a0> (entity: CDNewsSource; id: 0x600003099100 <x-coredata:///CDNewsSource/tAEF068C8-35C0-4287-8F13-84D6B5B35A6D3>; data: {
      name = nil;
      story =     (
      );
  }))

【问题讨论】:

  • 你真的要在这里创建一个新的源吗?您不应该查询现有源,并且仅在找不到匹配的现有源时才创建新源吗?您可以使用story.managedObjectContext 而不是context 在与批处理操作相同的上下文中进行操作。
  • 即使story 在闭包中是一个有效的NSManagedObjectstory.managedObjectContext 也是nil。这真的是您获得批量插入上下文的方式吗?
  • 是的,我想获得一个现有的源,但它们保存在容器的viewContext 中,所以我还没有弄清楚如何获取一个对象。我想我会缓存 NSManagedObjectID,虽然它看起来不稳定
  • 我要问的第一个问题是你真的需要使用批量插入吗?不要预先优化。只需在数据上使用一个简单的循环,随时插入每个实体,完成后插入saveContext。绝对不要缓存托管对象 ID。正如我所说,您应该能够访问批量插入上下文并对此执行查询。这是一个子上下文
  • 批量插入是重点,我试图更好地理解批量操作。

标签: ios swift core-data nsmanagedobject nsmanagedobjectcontext


【解决方案1】:

在 Apple 文档存档中,我找到了答案:

批量更新不能用于更改关系、删除实体或创建新实体。

来源:https://developer.apple.com/library/archive/featuredarticles/CoreData_Batch_Guide/BatchUpdates/BatchUpdates.html

【讨论】:

  • 那个来源实际上是关于 NSBatchUpdateRequest,而不是 NSBatchInsertRequest。请注意,它说它不能删除实体,但 NSBatchDeleteRequest 肯定可以删除实体。尽管如此,考虑到批处理请求直接在持久存储上操作,它们都无法改变关系,这似乎是合理的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多