.NET 5 中为何自定义Identity用户的自增列会被误更新及解决方法
问题根因
你碰到的报错不是你主动修改了membershipID,是两层配置叠出来的问题:
- ASP.NET Core Identity 自带的
IdentityUser本来就有一个字符串类型的主键Id,你给membershipID加了[Key]之后,相当于给模型塞了两个并列主键。EF Core不会直接在模型校验时拦这个配置,但生成SQL的时候会把所有标了Key的字段都拉进更新逻辑,既会当Where条件,也可能错误把它放进待更新的列集合。 - 就算你去掉了
[Key],还有个容易踩的默认逻辑坑:EF Core 追踪实体的时候,所有标了DatabaseGeneratedOption.Identity的字段,如果没显式配置更新行为,只要实体上这个属性有值,就会被标记为已修改。最后生成的UPDATE语句只要带上这个自增列,就会撞数据库“自增列不允许更新”的硬约束。
修复步骤
- 先把membershipID上的
[Key]注解删掉。Identity用户表的唯一主键就是框架自带的Id,membershipID只是个带自增属性的业务字段,根本没必要当主键。双主键的配置本身就会让EF的SQL生成逻辑乱掉。 - 显式配置这个字段的保存行为,强制EF在更新的时候忽略它,别把它放进UPDATE的列清单。推荐用Fluent API配,控制力比光靠数据注解强得多,直接写在你的DbContext的
OnModelCreating里就行:
protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.Entity<ApplicationUser>(entity => { // 配置自增业务字段MembershipID entity.Property(u => u.MembershipID) .UseIdentityColumn() // 声明是数据库自增列,插入时自动生成值 .ValueGeneratedOnAdd() // 仅在新增时生成值,更新流程不处理 // 更新保存时直接忽略这个字段的现有值,不生成对应的UPDATE列 .Metadata.AfterSaveBehavior = Microsoft.EntityFrameworkCore.Metadata.PropertyValueBehavior.Ignore; }); }
顺便提一句,把原来小写开头的membershipID改成大写开头的MembershipID,符合C#公开属性的命名规范,也能减少不必要的映射歧义。
- 检查你的更新逻辑:看看代码里读实体更新其他字段的时候,是不是不小心给membershipID赋了值——哪怕赋的是和原值完全一样的旧值,EF的变更追踪器也会把这个列标成已修改,照样会生成更新它的SQL。
- 改完配置之后,把之前生成的对应迁移删掉,重新生成迁移再更新数据库,避免旧迁移里的错误配置残留。
内容的提问来源于stack exchange,提问作者Seerex
相关产品推荐
相关产品推荐

