将DbContext改为IdentityDbContext后调用EnsureCreated()遇运行时错误
问题:ASP.NET EF项目切换到IdentityDbContext后EnsureCreated()抛出异常
我正尝试给ASP.NET Entity Framework项目添加授权认证功能,之前Context类继承DbContext,为了添加安全功能改成继承IdentityDbContext后,在Program.cs的context.Database.EnsureCreated();代码行抛出异常。
SchoolContext.cs代码
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using AdvisementApp.Models; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; namespace AdvisementApp.Data { public class SchoolContext : IdentityDbContext // 继承IdentityDbContext { public SchoolContext (DbContextOptions<SchoolContext> options) : base(options) { } public DbSet<AdvisementApp.Models.Student> Students { get; set; } = default!; public DbSet<Advisor> Advisors { get; set; } public DbSet<Major> Majors { get; set; } public DbSet<Course> Courses { get; set; } public DbSet<StudentCourse> StudentCourses { get; set; } public DbSet<MajorCourse> MajorCourses { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Student>().ToTable("Student"); modelBuilder.Entity<Course>().ToTable("Course"); modelBuilder.Entity<StudentCourse>().ToTable("StudentCourse"); modelBuilder.Entity<Major>().ToTable("Major"); modelBuilder.Entity<Advisor>().ToTable("Advisor"); modelBuilder.Entity<MajorCourse>().ToTable("MajorCourse"); modelBuilder.Entity<Advisor>() .HasMany(a => a.Students) .WithOne(s => s.Advisor) .HasForeignKey(s => s.AdvisorId); } } }
Program.cs代码
using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using AdvisementApp.Data; using Microsoft.AspNetCore.Identity; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddDbContext<SchoolContext>(options => options.UseSqlite(builder.Configuration.GetConnectionString("SchoolContext") ?? throw new InvalidOperationException("Connection string 'SchoolContext' not found."))); builder.Services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<SchoolContext>(); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddControllersWithViews(); builder.Services.Configure<IdentityOptions>(options => { // Password settings. options.Password.RequireDigit = true; options.Password.RequireLowercase = true; options.Password.RequireNonAlphanumeric = true; options.Password.RequireUppercase = true; options.Password.RequiredLength = 6; options.Password.RequiredUniqueChars = 1; // Lockout settings. options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); options.Lockout.MaxFailedAccessAttempts = 5; options.Lockout.AllowedForNewUsers = true; // User settings. options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"; options.User.RequireUniqueEmail = false; }); builder.Services.ConfigureApplicationCookie(options => { // Cookie settings options.Cookie.HttpOnly = true; options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.LoginPath = "/Identity/Account/Login"; options.AccessDeniedPath = "/Identity/Account/AccessDenied"; options.SlidingExpiration = true; }); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios app.UseHsts(); } else { app.UseDeveloperExceptionPage(); app.UseMigrationsEndPoint(); } using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; var context = services.GetRequiredService<SchoolContext>(); context.Database.EnsureCreated();// 异常发生在此行 DbInitializer.Initialize(context); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); app.UseAuthentication(); //app.UseAuthorization(); app.MapRazorPages(); app.Run();
异常截图

问题修复方案
- OnModelCreating必须调用基类方法
IdentityDbContext需要通过base.OnModelCreating(modelBuilder)来配置Identity相关的表结构(如AspNetUsers、AspNetRoles),你的代码重写该方法但未调用基类逻辑,导致EF无法生成必要的Identity表。修改SchoolContext的OnModelCreating:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 先执行基类的Identity表配置逻辑 base.OnModelCreating(modelBuilder); modelBuilder.Entity<Student>().ToTable("Student"); modelBuilder.Entity<Course>().ToTable("Course"); modelBuilder.Entity<StudentCourse>().ToTable("StudentCourse"); modelBuilder.Entity<Major>().ToTable("Major"); modelBuilder.Entity<Advisor>().ToTable("Advisor"); modelBuilder.Entity<MajorCourse>().ToTable("MajorCourse"); modelBuilder.Entity<Advisor>() .HasMany(a => a.Students) .WithOne(s => s.Advisor) .HasForeignKey(s => s.AdvisorId); }
- 替换EnsureCreated为迁移初始化
EnsureCreated()不支持EF迁移,若后续需要用迁移管理数据库结构,建议改用迁移初始化:
- 打开包管理器控制台,执行
Add-Migration InitialIdentity - 执行
Update-Database - 将Program.cs中的
context.Database.EnsureCreated();替换为:context.Database.Migrate();
- 修正中间件顺序
认证/授权中间件必须放在路由之后、端点之前,修改Program.cs的中间件顺序:
app.UseRouting(); // 认证、授权中间件移到此处 app.UseAuthentication(); app.UseAuthorization(); // 取消注释该行 app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); });
内容的提问来源于stack exchange,提问作者Jaiylon
相关产品推荐
相关产品推荐

