EF6新增UserToSupervisors映射记录时SupervisorId被异常覆盖问题
问题原因
这是EF6自带的**关系自动修正(Relationship Fix-up)**机制导致的外键覆盖,核心问题出在你添加映射记录的挂载位置错误:
- 执行
userDo.Supervisor = new Supervisor { Id = userDo.Id, Type = "GROUP LEADER" }时,EF已经跟踪到这个新创建的Supervisor实体主键就是当前用户ID。 - 后续你往
userDo.Supervisor.UserToSupervisors集合里新增映射记录时,EF会默认集合内所有关联记录的外键SupervisorId必须和所属的Supervisor实体主键一致。哪怕你手动给SupervisorId赋了其他值,在执行SaveChanges时,EF的关系校验逻辑会判定这个值和导航属性关联不一致,自动把它覆盖为当前所属Supervisor的ID——也就是当前用户自己的ID。
简单说:你把「当前用户和所选上级主管的映射关系」,错误挂载到了「当前用户自己的主管身份实体」的集合下,EF自然会把外键修正为这个集合所属的主管ID。另外你贴的代码里GetSelectedGroupLeaderId后没有加调用括号,如果这是方法而非属性,本身也会存在取值错误。
修复方案
二选一即可,优先推荐方案一,逻辑更直观:
方案一:直接将映射记录加入上下文对应实体集
不要把映射记录挂载到新建的Supervisor导航属性集合下,单独创建映射实体后,直接加入UserToSupervisors对应的DbSet,EF不会自动覆盖你手动赋值的外键:
// 绑定当前用户自身的主管身份 userDo.Supervisor = new Supervisor { Id = userDo.Id, Type = "GROUP LEADER" }; // 单独创建映射关系,直接加入上下文的映射表DbSet var mapping = new UserToSupervisor { UserId = userDo.Id, SupervisorId = GetSelectedGroupLeaderId() // 方法记得加调用括号 }; dbContext.UserToSupervisors.Add(mapping); // 提交用户实体 userDao.Add(userDo); dbContext.SaveChanges();
方案二:往正确的主管实体的导航集合添加记录
先查询到你选中的上级主管实体,再把映射记录加入这个已存在的主管的UserToSupervisors集合,EF会自动匹配正确的外键,不会出现覆盖:
// 绑定当前用户自身的主管身份 userDo.Supervisor = new Supervisor { Id = userDo.Id, Type = "GROUP LEADER" }; // 查询到选中的上级主管实体 var targetSupervisor = dbContext.Supervisors.Find(GetSelectedGroupLeaderId()); // 往目标主管的集合里添加映射,不需要手动指定SupervisorId targetSupervisor.UserToSupervisors.Add(new UserToSupervisor { UserId = userDo.Id }); // 提交 userDao.Add(userDo); dbContext.SaveChanges();
注意:不要尝试通过关闭EF的自动关系修正来解决这个问题,会引发更多实体跟踪不一致的问题,从挂载逻辑上修正才是正确做法。
内容的提问来源于stack exchange,提问作者Abbas
相关产品推荐
相关产品推荐

