ASP.NET Core 3.1数据库优先更新模型时IdentityDbContext自动变更问题
我之前也遇到过完全一样的问题——每次用数据库优先更新模型,Identity上下文的继承关系和OnModelCreating里的base调用就被冲掉,导致身份验证报错,折腾了好久终于找到靠谱的解决办法,分享给你:
问题根源
数据库优先的Scaffold-DbContext工具本质是根据当前数据库结构重新生成上下文代码,它默认只会生成继承DbContext的类,而且会完全覆盖原有的OnModelCreating方法,根本不会保留你手动加的Identity相关自定义逻辑,这就是为什么每次更新后都要手动修改的原因。
解决方案1:用Scaffold命令指定基类(一劳永逸)
每次执行更新模型的Scaffold命令时,加上-BaseClass参数,直接指定上下文的基类为IdentityDbContext<ApplicationUser>,这样生成的上下文会自动继承Identity的上下文,不用再手动修改基类。
举个Package Manager Console里的命令例子:
Scaffold-DbContext "Server=xxx;Database=dd;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Context QuizVContext -BaseClass "Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext<YourNamespace.ApplicationUser>"
记得把YourNamespace换成你项目的实际命名空间,这样生成的QuizVContext就会自动继承IdentityDbContext<ApplicationUser>,再也不会变回DbContext了。
解决方案2:用分部类分离自定义逻辑(避免代码被覆盖)
因为自动生成的上下文是partial类,我们可以把Identity相关的自定义逻辑单独放在一个分部类文件里,这样即使工具覆盖了自动生成的文件,我们的自定义代码也不会丢。
具体步骤:
- 新建一个文件,比如叫
QuizVContext.Identity.cs,写下面的代码:
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace YourNamespace.Models // 必须和自动生成的上下文命名空间一致 { public partial class QuizVContext : IdentityDbContext<ApplicationUser> { // 重写构造函数,匹配IdentityDbContext的构造函数 public QuizVContext() : base() { } public QuizVContext(DbContextOptions<QuizVContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { // 先执行Identity的默认模型配置,这步就是解决主键报错的关键 base.OnModelCreating(modelBuilder); // 再执行自动生成的数据库实体配置 OnModelCreatingGenerated(modelBuilder); } // 声明一个partial方法,让自动生成的上下文实现它 partial void OnModelCreatingGenerated(ModelBuilder modelBuilder); } }
- 修改自动生成的
QuizVContext.cs里的OnModelCreating方法,把它改成partial方法并重命名为OnModelCreatingGenerated:
protected partial void OnModelCreatingGenerated(ModelBuilder modelBuilder) { // 这里保留工具自动生成的所有实体配置代码 modelBuilder.Entity<AspNetRoles>(entity => { entity.Property(e => e.Id).HasMaxLength(128); entity.Property(e => e.Name).IsRequired(); }); // ... 其他自动生成的实体配置代码 }
这样每次更新模型时,工具只会更新OnModelCreatingGenerated里的内容,而我们包含base.OnModelCreating的OnModelCreating方法会一直保留在分部类里,再也不用手动添加了。
关于那个主键报错的原因
当你删掉base.OnModelCreating(modelBuilder)时,Identity框架的默认模型配置就没执行——它本来会自动给IdentityUserLogin这些Identity实体配置主键和关系,现在EF Core识别不了这些实体的主键,自然就抛出那个错误了,加上base调用就搞定了。
内容的提问来源于stack exchange,提问作者xaify

