setDeleted 循环导致在 saveChanges 调用中修改实体
setDeleted loop resulting in modified entities in saveChanges call
我正在尝试删除对象层次结构:
客户->订单->OrderItems->OrderItemOptions
我设置了一个简单的嵌套循环,试图甚至按 "correct" 顺序执行操作,因为它们必须在数据库中完成 - 在删除父记录之前先删除子记录。
这是循环:
deleteCustomer(customer: Customer): Promise<void> {
return this.getCustomerOrderHistory(customer.id).then(orders => {
orders.forEach(o => {
o.items.forEach(oi => {
oi.options.forEach(opt => opt.entityAspect.setDeleted());
oi.entityAspect.setDeleted();
});
o.entityAspect.setDeleted();
});
customer.entityAspect.setDeleted();
});
}
问题在于,当每一级的父对象被setDeleted()时,一组重复的实体记录被标记为"modified"被添加到EntityManager缓冲的变化中。然后,当我调用 saveChanges 时,ASP.NET/EF 后端抛出异常,因为在执行与这些修改记录相对应的 UPDATE 语句时,DELETE 已经发生,因此 UPDATE 失败并返回 FK not发现某种异常。
那么我在这里错过了什么?
这是在遍历数组的同时修改数组的经典案例。当我们像这样删除 children 时:
o.items.forEach(oi => {
oi.entityAspect.setDeleted();
});
…每次我们调用setDeleted
,它都会从parentitems
集合中移除child实体,这是被迭代的集合。所以下一次迭代会跳过中间的实体,实际上只有大约一半的实体被设置为删除。
这将是一个包含已删除和已修改实体混合的 SaveBundle,并且(如果您正在删除 parent 实体),当您尝试删除时,数据库中的外键违规parent而不删除所有children.
简单的解决方案是在迭代之前复制数组,例如使用 slice
:
o.items.slice().forEach(oi => {
oi.entityAspect.setDeleted();
});
我正在尝试删除对象层次结构:
客户->订单->OrderItems->OrderItemOptions
我设置了一个简单的嵌套循环,试图甚至按 "correct" 顺序执行操作,因为它们必须在数据库中完成 - 在删除父记录之前先删除子记录。
这是循环:
deleteCustomer(customer: Customer): Promise<void> {
return this.getCustomerOrderHistory(customer.id).then(orders => {
orders.forEach(o => {
o.items.forEach(oi => {
oi.options.forEach(opt => opt.entityAspect.setDeleted());
oi.entityAspect.setDeleted();
});
o.entityAspect.setDeleted();
});
customer.entityAspect.setDeleted();
});
}
问题在于,当每一级的父对象被setDeleted()时,一组重复的实体记录被标记为"modified"被添加到EntityManager缓冲的变化中。然后,当我调用 saveChanges 时,ASP.NET/EF 后端抛出异常,因为在执行与这些修改记录相对应的 UPDATE 语句时,DELETE 已经发生,因此 UPDATE 失败并返回 FK not发现某种异常。
那么我在这里错过了什么?
这是在遍历数组的同时修改数组的经典案例。当我们像这样删除 children 时:
o.items.forEach(oi => {
oi.entityAspect.setDeleted();
});
…每次我们调用setDeleted
,它都会从parentitems
集合中移除child实体,这是被迭代的集合。所以下一次迭代会跳过中间的实体,实际上只有大约一半的实体被设置为删除。
这将是一个包含已删除和已修改实体混合的 SaveBundle,并且(如果您正在删除 parent 实体),当您尝试删除时,数据库中的外键违规parent而不删除所有children.
简单的解决方案是在迭代之前复制数组,例如使用 slice
:
o.items.slice().forEach(oi => {
oi.entityAspect.setDeleted();
});