错误 - 在批量插入期间设置关系时不同上下文中的对象
Error - objects in different contexts when setting relationship during a batch insert
我有一个函数用于在我的应用程序中创建对象图以进行测试。目前数据结构非常简单,Patient和ParameterMeasurement实体之间是一对多的关系。
由于测试状态的设置涉及大约 800 个条目,因此将其作为批量插入进行是有意义的......直到您尝试建立 ParameterMeasurement 和 Patient 之间的关系(反过来,它是一个一对一)此时应用程序崩溃并出现可怕的“非法尝试在不同上下文中的对象之间建立关系'cdPatient'”
我很难理解为什么会发生这种情况,因为 Patient 和 ParameterMeasurement 实体都是使用调用者传递给函数的相同托管对象上下文创建的。
我已经尝试存储 Patient 的 objectID(在实例化 ParameterMeasurement 实例之前创建),然后在批量插入闭包中创建 Patient 实例的本地副本(代码在下面,但注释掉了)但是这个不能解决问题。我也检查了我的模型(一切正常,关系很好),删除了应用程序并重置了 sim 但仍然没有快乐。
最后,我坚持使用 print 语句来检查在实例化时与两个实体关联的 MOC 以及传递给函数的 MOC。正如预期的那样,内存地址匹配,这使得错误消息看起来像是一条红鲱鱼。
谁能指出我正确的方向?这似乎是过去的一个常见问题(5 年前有很多关于 ObjC 的帖子,但在 Swift 中很少),但是上面的例子没有处理这个特定的场景。
func addSampleData(to context: NSManagedObjectContext) throws {
try addParameterDefinitions(to: context, resetToDefaults: true)
let fetchRequest = ParameterProfile.fetchAll
let profiles = try context.fetch(fetchRequest)
for _ in 1...10 {
let patient = Patient(context: context)
patient.cdName = "Patient \(UUID().uuidString.split(separator: "-")[0])"
patient.cdCreationDate = Date()
// let patientID = patient.objectID
for profile in profiles {
let data: [(Date, Double)] = DataGenerator.placeholderDataForParameter(with: profile)
var idx = 0
let total = data.count
let batchInsert = NSBatchInsertRequest(entity: ParameterMeasurement.entity()) { (managedObject: NSManagedObject) -> Bool in
guard idx < total else { return true }
// let patientInContext = context.object(with: patientID) as! Patient
if let measurement = managedObject as? ParameterMeasurement {
// measurement.cdPatient = patientInContext
measurement.cdPatient = patient
measurement.cdName = profile.cdName
measurement.cdTimestamp = data[idx].0
measurement.cdValue = data[idx].1
}
idx += 1
return false
}
do {
try context.execute(batchInsert)
try context.save()
} catch {
fatalError("Import failed with error: \(error.localizedDescription)")
}
}
}
}
核心数据模型定义:
对此进行了更多挖掘,似乎无法使用批量插入将关系添加到持久存储 as noted here。我猜这是因为在此过程中与正确关联实体相关的困难 - 令人沮丧但不会破坏交易。
现在,我将恢复到实体的单独插入,尽管我可以分两次完成该过程,即批量插入“基本”属性和第二次设置插入实体的关系。不过,在这个级别上似乎付出了太多的努力,而且对于额外的代码复杂性(以及错误的风险!),任何时间节省都可能是最小的!
我有一个函数用于在我的应用程序中创建对象图以进行测试。目前数据结构非常简单,Patient和ParameterMeasurement实体之间是一对多的关系。
由于测试状态的设置涉及大约 800 个条目,因此将其作为批量插入进行是有意义的......直到您尝试建立 ParameterMeasurement 和 Patient 之间的关系(反过来,它是一个一对一)此时应用程序崩溃并出现可怕的“非法尝试在不同上下文中的对象之间建立关系'cdPatient'”
我很难理解为什么会发生这种情况,因为 Patient 和 ParameterMeasurement 实体都是使用调用者传递给函数的相同托管对象上下文创建的。
我已经尝试存储 Patient 的 objectID(在实例化 ParameterMeasurement 实例之前创建),然后在批量插入闭包中创建 Patient 实例的本地副本(代码在下面,但注释掉了)但是这个不能解决问题。我也检查了我的模型(一切正常,关系很好),删除了应用程序并重置了 sim 但仍然没有快乐。
最后,我坚持使用 print 语句来检查在实例化时与两个实体关联的 MOC 以及传递给函数的 MOC。正如预期的那样,内存地址匹配,这使得错误消息看起来像是一条红鲱鱼。
谁能指出我正确的方向?这似乎是过去的一个常见问题(5 年前有很多关于 ObjC 的帖子,但在 Swift 中很少),但是上面的例子没有处理这个特定的场景。
func addSampleData(to context: NSManagedObjectContext) throws {
try addParameterDefinitions(to: context, resetToDefaults: true)
let fetchRequest = ParameterProfile.fetchAll
let profiles = try context.fetch(fetchRequest)
for _ in 1...10 {
let patient = Patient(context: context)
patient.cdName = "Patient \(UUID().uuidString.split(separator: "-")[0])"
patient.cdCreationDate = Date()
// let patientID = patient.objectID
for profile in profiles {
let data: [(Date, Double)] = DataGenerator.placeholderDataForParameter(with: profile)
var idx = 0
let total = data.count
let batchInsert = NSBatchInsertRequest(entity: ParameterMeasurement.entity()) { (managedObject: NSManagedObject) -> Bool in
guard idx < total else { return true }
// let patientInContext = context.object(with: patientID) as! Patient
if let measurement = managedObject as? ParameterMeasurement {
// measurement.cdPatient = patientInContext
measurement.cdPatient = patient
measurement.cdName = profile.cdName
measurement.cdTimestamp = data[idx].0
measurement.cdValue = data[idx].1
}
idx += 1
return false
}
do {
try context.execute(batchInsert)
try context.save()
} catch {
fatalError("Import failed with error: \(error.localizedDescription)")
}
}
}
}
核心数据模型定义:
对此进行了更多挖掘,似乎无法使用批量插入将关系添加到持久存储 as noted here。我猜这是因为在此过程中与正确关联实体相关的困难 - 令人沮丧但不会破坏交易。
现在,我将恢复到实体的单独插入,尽管我可以分两次完成该过程,即批量插入“基本”属性和第二次设置插入实体的关系。不过,在这个级别上似乎付出了太多的努力,而且对于额外的代码复杂性(以及错误的风险!),任何时间节省都可能是最小的!