.NET 1.1.4迁移至2.0.0后执行dotnet ef update遇DbInitializer报错
这个问题我之前帮同事排查过,本质是.NET Core 2.0对Identity实体的配置规则做了调整,和1.x版本的处理逻辑不一样。
问题根源
在.NET Core 1.x中,你可能习惯在派生的ApplicationUser里手动配置主键,但到了2.0版本,根类型IdentityUser已经默认内置了主键(也就是Id字段)的配置逻辑。如果你在派生类ApplicationUser里再尝试通过特性或Fluent API配置主键,EF就会抛出你看到的这个异常——因为主键必须在根类型上定义,派生类不能重复配置。
具体解决步骤
移除ApplicationUser类中的[Key]特性
检查你的ApplicationUser代码,如果有类似下面的写法,把[Key]特性删掉:public class ApplicationUser : IdentityUser { // 删掉这行[Key]! [Key] public override string Id { get; set; } // 你的自定义字段... }IdentityUser已经为Id字段标记了主键,不需要你重复操作。移除DbContext中针对ApplicationUser的HasKey配置
打开你的DbContext类,找到OnModelCreating方法,如果有配置ApplicationUser主键的代码,直接删除:protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 删掉这行HasKey配置! modelBuilder.Entity<ApplicationUser>().HasKey(u => u.Id); // 其他自定义配置保留... }调用
base.OnModelCreating(modelBuilder)时,Identity框架已经会自动处理根类型的主键配置了。如果使用自定义主键类型的特殊情况
如果你需要把主键从默认的string改成int或其他类型,要在继承IdentityUser时指定泛型参数,同时DbContext也要对应调整:// 自定义主键为int的ApplicationUser public class ApplicationUser : IdentityUser<int> { // 你的自定义字段... } // 对应的DbContext public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole<int>, int> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } // 其他DbSet定义... }这种情况下,根类型
IdentityUser<int>已经配置好主键,派生类同样不需要额外操作。
最后一步
完成上述调整后,重新运行dotnet ef database update命令,应该就能正常执行迁移了。如果之前生成的迁移文件有冲突,建议先备份数据,然后删除旧的迁移文件,重新生成新的迁移(dotnet ef migrations add [MigrationName])再执行更新。
内容的提问来源于stack exchange,提问作者user6728767

