核心数据 - 使用 NSBatchInsertRequest 设置多对一关系
Posted
技术标签:
【中文标题】核心数据 - 使用 NSBatchInsertRequest 设置多对一关系【英文标题】:Core data - Set many-to-one relationship with NSBatchInsertRequest 【发布时间】:2020-12-31 17:11:17 【问题描述】:我有两个实体,User
和 Post
。一个User
包含许多Post
,而每个Post
只有一个User
。
我正在尝试批量插入超过 1000 个帖子。
private func newBatchInsertRequest(with posts: [PostData]) -> NSBatchInsertRequest
var index = 0
let total = posts.count
let batchInsert = NSBatchInsertRequest(entity: Post.entity()) (managedObject: NSManagedObject) -> Bool in
guard index < total else return true
if let post = managedObject as? Post
let data = posts[index]
post.createdData = data.createdDate
post.identifier = data.identifier
post.text = data.text
index += 1
return false
PersistenceController.shared.container.performBackgroundTask context in
try? context.execute(batchInsert)
try? context.save()
它会插入我想要插入的所有帖子。但是,我无法配置如何设置他们的User
。
我尝试使用以下代码,但没有成功。
let updateRequest = NSBatchUpdateRequest(entity: Post.entity())
updateRequest.resultType = .updatedObjectIDsResultType
updateRequest.propertiesToUpdate = ["user": user]
try? context.execute(updateRequest)
我收到以下错误。
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid relationship ((<NSRelationshipDescription: 0x2801045a0>), name item, isOptional 1, isTransient 0, entity Post, renamingIdentifier item
我可以一一设置他们的用户,但是处理时间长,效率低。
如何更高效地更新 Posts 的用户属性?
更新
所有这些帖子都属于一个User
,它还不存在。我需要在执行NSBatchInsertRequest
之前或之后创建它。
User
具有三个属性
1. createdDate: Date
2. identifier: UUID
3. name: String
我的目标是使用NSBatchInsertRequest
或在私有上下文中插入属于一个使用的帖子,这样它就不会阻塞主线程。
【问题讨论】:
不清楚您如何确定应该将哪个用户连接到帖子? 那为什么不先创建用户,然后分配给newBatchInsertRequest中的帖子呢? 他们有不同的上下文。在核心数据中,绑定到一个上下文的对象不能在另一个上下文中使用。 @JoakimDanielson 【参考方案1】:这是我会尝试的:
在批处理操作之前创建User
。是的,它将在不同的环境中——只要确保你抓住它的NSManagedObjectID
(它是NSManagedObject
上的一个属性)并将它保存在一个私有属性上。
在您的PersistenceController.shared.container.performBackgroundTask
中,您可以引用您的私人上下文。使用之前的托管对象 ID 在您的私有上下文中获取/注册相同的 User
:
let user = context.object(with: userManagedObjectID)
然后将此用户传递给创建批量插入请求的方法,以设置 Post
对象的用户属性。
我相信,如果您在数据模型编辑器中设置了反向关系,则无需填充 User.posts
。这应该会为您自动发生。
【讨论】:
谢谢。这没用。我在PersistenceController.shared.container.performBackgroundTask
之前创建了一个用户并将context.object(with: userManagedObjectID)
分配给post.user
。得到这个错误:'非法尝试在不同上下文中的对象之间建立关系'u'ser【参考方案2】:
我以不同的方式解决了这个问题。
-
在我的实体中需要添加关系占位符属性的 tmpID。
创建批量插入时,将 tmpID 设置为特定字符串。例如父对象ID parent.objectID。
正在执行批量插入。
然后使用 tmpID 从 CoreData 获取所有对象。
然后扔掉所有人并设置:
-
关系
tmpID 为 nil,不留内存。
【讨论】:
以上是关于核心数据 - 使用 NSBatchInsertRequest 设置多对一关系的主要内容,如果未能解决你的问题,请参考以下文章