EF Core中Guid主键关联实体状态为Modified而非Added的问题
嘿,我一眼就揪出问题所在了——你的OnModelCreating配置里犯了个很容易忽略的低级错误!
问题根源
你在配置AppUserConfig实体的时候,重复写了modelBuilder.Entity<AppUser>().HasKey(x => x.Id);,完全没给AppUserConfig配置正确的主键。EF Core没法识别AppUserConfig的主键字段,当你创建新的AppUserConfig实例并添加到父实体集合时,它错误地认为这个实体已经存在于数据库中,所以把状态标记成了Modified而非预期的Added,自然在SaveChanges时会因为找不到对应数据抛出异常。
解决方案步骤
1. 修正实体主键配置
打开你的TestDbContext,找到OnModelCreating方法,把AppUserConfig的主键配置修正过来:
原来的错误代码片段:
modelBuilder.Entity<AppUserConfig>().ToTable("TB_AppUserConfig"); modelBuilder.Entity<AppUser>().HasKey(x => x.Id); // 这里重复配置AppUser主键,完全错误
改成正确的配置:
modelBuilder.Entity<AppUserConfig>().ToTable("TB_AppUserConfig"); modelBuilder.Entity<AppUserConfig>().HasKey(x => x.Id); // 现在是配置AppUserConfig的主键了
完整的修正后OnModelCreating代码:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<AppUser>().ToTable("TB_AppUser"); modelBuilder.Entity<AppUser>().HasKey(x => x.Id); modelBuilder.Entity<AppUser>() .HasMany(x => x.AppUserConfigs) .WithOne() .HasForeignKey(x => x.UserId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity<AppUserConfig>().ToTable("TB_AppUserConfig"); // 修正:正确配置AppUserConfig的主键 modelBuilder.Entity<AppUserConfig>().HasKey(x => x.Id); }
2. 验证实体状态
修正配置后再运行代码,你会发现userConfig的状态已经变成Added了。这时调用dbContext.SaveChanges()就能正常把新的子实体插入数据库,不会再抛出UpdateException。
3. 可选优化:让数据库自动生成Guid主键
如果你不需要手动指定Guid主键,推荐让EF Core和数据库自动生成,能避免手动创建可能带来的潜在问题。只需要在实体配置里加上ValueGeneratedOnAdd():
// 给AppUser配置自动生成主键 modelBuilder.Entity<AppUser>() .Property(x => x.Id) .ValueGeneratedOnAdd(); // 给AppUserConfig配置自动生成主键 modelBuilder.Entity<AppUserConfig>() .Property(x => x.Id) .ValueGeneratedOnAdd();
之后你就可以修改实体构造函数,不用再手动传入Id参数,EF Core会在保存时自动生成唯一的Guid值。
测试修正后的代码
不管是先初始化父实体并保存,还是直接加载已存在的父实体添加子实体,现在都能正常执行SaveChanges(),子实体也会被正确插入数据库。
内容的提问来源于stack exchange,提问作者wushizhan

