繁体   English   中英

EF Core 3.1删除具有子关系的父实体+保存更改+在新父中重用相同的子ID =并发异常

[英]EF Core 3.1 Removing parent entity with child relations + save changes + reuse same child id in new parent = concurrent exception

做任何事情之前的情况:

class Parent: { int ParentId, Child Children: [] }
class Child: { int ChildId, int ParentId }
db.Parents: [{ ParentId: 1, Children:[ ChildId: 10, ParentId: 1] })
db.Children: [{ ChildId: 10, ParentId: 1 })

我正在尝试做类似的事情:

...
using var db = new DB();
var entity = await db.Parents.FirstOrDefaultAsync(e => e.ParentId == 1);
db.WorkdayResults.Remove(entity);
await db.SaveChangesAsync(); // After saving: db.Parents and db.Children will be empty
var entry = await db.Parents.AddAsync(new Parent{});
// entry.Entity.Children.Add(new Child {}); // This works
entry.Entity.Children.Add(new Child { ChildId: 1 }); // This does not work
await db.SaveChangesAsync() // Getting concurrent exception here
...

我不想更改逻辑,例如:首先保存父级,创建新上下文,然后使用旧的 ChildId 保存子级。 那么你们有什么好的解决方案吗? 这是 EF Core 还是 Devart MySql 功能?

你有一个错误。 您需要 ParentId 键来添加孩子。 既然你的数据库是空的,现在尝试使用这个:

[]Child children= { new Child {ParentId=1, ChildrenId=10}}
db.Parents.Add(new Parent { ParentId=1 , Chilren=  children}; 

或者,如果您的 dbcontext 配置正确,您可以尝试逆向:

db.Children.Add( new Child { ChidrentId=10, Parent= new Parent {ParentId=1}}

但是,如果您的 Id 是自动种子并且您的 dbcontext 配置正确,那就足够了:


db.Parents.Add(new Parent { Children= { new Child {}} }; 

只有当你已经有一个父 object 时,你才能像这样使用:

db.Children.Add( new Child {ParentId=...,ChildId=...})

就像主题说它是并发异常一样,所以我调试并发现如果我使用旧的 ChildId,EF 核心出于某种原因确实将实体 state 设置为“已修改”,即使旧实体不再存在于上下文中. 所以这是一个非常简单的解决方案:

db.Entry(childEntity).State = EntityState.Added;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM