EF Core循环插入TaskSchedule时第二次循环保存报错如何解决
报错根因
你代码里的对象复制逻辑存在根本性错误:
TaskSchedule copyTaskSchedule = new TaskSchedule(); copyTaskSchedule = taskSchedule;
你先创建了新的TaskSchedule实例,但下一行直接把原taskSchedule的引用赋值给了copyTaskSchedule,全程循环都在操作同一个被EF上下文跟踪的原实例:
- 第一次循环时你修改原实例Id为0,加入上下文后SaveChanges成功,此时EF上下文已经跟踪了这个实例,状态变为已持久化
- 第二次循环你再次修改这个已跟踪实例的属性、尝试重新添加时,EF会认为你要修改已有实体的主键关联字段,和中间表
userTask的外键约束冲突,直接抛出异常。
解决方法
把引用赋值改为属性复制,生成全新的TaskSchedule实例,避免操作同一个被跟踪的对象:
foreach(int user in users){ // 手动复制属性,生成全新的实例,不使用原实例引用 TaskSchedule copyTaskSchedule = new TaskSchedule { Title = taskSchedule.Title, Start = taskSchedule.Start, End = taskSchedule.End, isClosed = taskSchedule.isClosed, isDeleted = taskSchedule.isDeleted, priorityLevel = taskSchedule.priorityLevel, hasTimeLimit = taskSchedule.hasTimeLimit, customerId = taskSchedule.customerId, // 不需要复制导航属性,保持为空即可 Notes = null, Attachments = null, UserTasks = null, userLastEditId = taskSchedule.userLastEditId, userLastEditDate = taskSchedule.userLastEditDate, taskCreatedDate = taskSchedule.taskCreatedDate }; _context.TaskSchedules.Add(copyTaskSchedule); // 直接在内存里关联中间表,不用先存TaskSchedule再拿Id userTask copyUserTask = new userTask { TaskSchedule = copyTaskSchedule, UserId = user }; _context.userTasks.Add(copyUserTask); } // 最后统一提交,减少数据库交互次数 _context.SaveChanges();
如果属性太多不想手动写,也可以用MemberwiseClone做浅拷贝:
// 先给TaskSchedule加个克隆方法 public TaskSchedule Clone() { return (TaskSchedule)this.MemberwiseClone(); } // 循环里直接调用 var copyTaskSchedule = taskSchedule.Clone(); copyTaskSchedule.Id = 0; copyTaskSchedule.Notes = null; copyTaskSchedule.UserTasks = null; // 后续逻辑同上
额外优化建议
如果你的EF Core版本支持,多对多关联也可以不用显式操作中间表userTask,直接给新的TaskSchedule的UserTasks属性赋值即可,代码会更简洁。
内容的提问来源于stack exchange,提问作者GolfBravo
相关产品推荐
相关产品推荐

