使用EF Core 5向SQL Server插入一对多关联多条父子数据报错如何解决?
问题根因
核心问题有3个:
- 复用了同一个子实体集合:你创建的
lstChild是全局唯一的实例集合,同时赋值给两个Parent的子导航属性。EF Core变更追踪器只会将这组子实体关联到第一个被追踪的父实体上,第二个父实体关联的是已被追踪的子实体,不会生成新的子记录,也不会关联到第二个父实体。 - 异步方法未加
await:你调用的AddRangeAsync、SaveChangesAsync都是异步方法,未使用await等待执行完成,会导致数据插入逻辑执行异常。 - 实体类存在语法错误:
Child类上的外键特性拼写错误,正确写法为[ForeignKey("ParentId")],不要加空格;Parent类的子导航属性名建议统一大小写,避免赋值时大小写不匹配。
正确实现代码
每个父实体必须对应独立的子实体集合,不能复用同一个子实例列表,修正后代码如下:
// 修正后的实体类 public class Parent { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long Id {get; set;}// 自增主键 public string Name { get; set;} // 子导航属性,初始化避免空引用 public List<Child> Children { get; set;} = new List<Child>(); } public class Child { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long Id { get; set;} // 自增主键 public string ChildName { get; set;} public long ParentId { get; set;} // 修正外键特性拼写 [ForeignKey("ParentId")] public Parent Parent { get; set;} } // 插入逻辑 public async Task Main(string[] args) { List<Parent> lstparents = new List<Parent>() { // 第一个父实体独立创建子集合 new Parent { Name = "xyz", Children = new List<Child>() { new Child{ ChildName= "Child1Name"}, new Child{ ChildName= "Child2Name"}, new Child{ ChildName= "Child3Name"} } }, // 第二个父实体独立创建子集合,不共享子实例 new Parent { Name = "xyz1", Children = new List<Child>() { new Child{ ChildName= "Child1Name"}, new Child{ ChildName= "Child2Name"}, new Child{ ChildName= "Child3Name"} } } }; // 异步方法添加await等待执行 await Context.AddRangeAsync(lstparents); await Context.SaveChangesAsync(); }
原方案错误说明
- 方案1:遍历父实体时重复Add同一个子实例列表,变更追踪器只会为子实例生成一次插入语句,仅关联第一个父实体,其余父实体无对应子数据。
- 方案2:手动将同一个子实例多次标记为
Added状态,EF Core会尝试为同一个实例执行多次插入,第一次插入后子实例已经获得自增ID,第二次插入时EF会携带这个ID尝试写入自增列,触发IDENTITY_INSERT is set to OFF报错。
内容的提问来源于stack exchange,提问作者Manoj Raut
相关产品推荐
相关产品推荐

