C# EntityFramework 6 修改子实体状态后如何保存子实体数据
问题排查及修复方案
核心错误点
- 多余的
Add操作:从当前上下文查询出的usr对象默认已经被上下文跟踪,调用context.Users.Add(usr)会将该对象标记为新增状态,保存时要么触发主键重复异常,要么生成冗余的用户数据,直接删除这行代码即可。 - 语法错误:
context.SaveChanges()末尾缺少分号,会导致编译不通过。 - 导航属性外键映射缺失:当前
User实体的User2导航属性未配置和ManagerEmployeeNo字段的外键关联,EF无法识别导航属性修改对应的外键更新,导致修改无法持久化。 - 可选优化:查询下属列表时直接遍历
IQueryable会触发多次数据库查询,建议调用ToList()立即加载所有下属数据。
修正后的代码
实体类修正
[Table("org.User")] public partial class User { public int ID { get; set; } // 补充原代码遗漏的主键字段定义 public string PersonNumber { get; set; } public bool Disabled { get; set; } // 补充原代码用到的Disabled字段定义 /// <summary> /// User Manager /// </summary> [ForeignKey(nameof(ManagerEmployeeNo))] // 新增外键注解,关联导航属性和外键字段 public virtual User User2 { get; set; } public string ManagerEmployeeNo { get; set; } }
业务逻辑修正
public class SapService { // 补充原代码遗漏的外层方法定义 public void UpdateUserSubordinates(int userId) { using (var context = new Data.OrganisationContext()) { var usr = (from user in context.Users where user.ID == userId select user).FirstOrDefault(); // 新增空判断,避免空引用异常 if (usr == null) return; UpdateSubOrdinatesManagerReference(context, usr); context.SaveChanges(); // 补充分号 } } private void UpdateSubOrdinatesManagerReference(Data.OrganisationContext orgContext, Data.User user) { var subordinates = orgContext.Users .Where(subordinate => subordinate.ManagerEmployeeNo == user.PersonNumber && !subordinate.Disabled) .ToList(); // 新增ToList立即加载数据,避免多次查询 foreach (var subordinate in subordinates) subordinate.User2 = user; } }
额外验证点
如果修改后还是无法保存,可检查以下配置:
- 检查
OrganisationContext中是否通过Fluent API配置了User实体的导航属性规则,避免和注解配置冲突 - 开启EF日志输出,查看生成的SQL语句是否包含下属表的Update语句,确认修改是否被上下文检测到
内容的提问来源于stack exchange,提问作者Mukil Deepthi
相关产品推荐
相关产品推荐

