【发布时间】: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,这可能与NSBatchInsertRequest 的managedObjectHandler 中使用的背景上下文不同。不清楚这是怎么回事,因为我在执行和创建批量插入请求时指定了上下文。
完整的错误日志
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在闭包中是一个有效的NSManagedObject,story.managedObjectContext也是nil。这真的是您获得批量插入上下文的方式吗? -
是的,我想获得一个现有的源,但它们保存在容器的
viewContext中,所以我还没有弄清楚如何获取一个对象。我想我会缓存 NSManagedObjectID,虽然它看起来不稳定 -
我要问的第一个问题是你真的需要使用批量插入吗?不要预先优化。只需在数据上使用一个简单的循环,随时插入每个实体,完成后插入
saveContext。绝对不要缓存托管对象 ID。正如我所说,您应该能够访问批量插入上下文并对此执行查询。这是一个子上下文 -
批量插入是重点,我试图更好地理解批量操作。
标签: ios swift core-data nsmanagedobject nsmanagedobjectcontext