You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将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();

异常截图

异常截图


问题修复方案

  1. 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);
}
  1. 替换EnsureCreated为迁移初始化
    EnsureCreated()不支持EF迁移,若后续需要用迁移管理数据库结构,建议改用迁移初始化:
  • 打开包管理器控制台,执行Add-Migration InitialIdentity
  • 执行Update-Database
  • 将Program.cs中的context.Database.EnsureCreated();替换为:
    context.Database.Migrate();
    
  1. 修正中间件顺序
    认证/授权中间件必须放在路由之后、端点之前,修改Program.cs的中间件顺序:
app.UseRouting();

// 认证、授权中间件移到此处
app.UseAuthentication();
app.UseAuthorization(); // 取消注释该行

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
});

内容的提问来源于stack exchange,提问作者Jaiylon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 10:40:18