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

.NET 10自定义IdentityDbContext时EF Core迁移未生成AspNetUserPasskeys表

修复.NET 10 Blazor身份认证项目中AspNetUserPasskeys表缺失的迁移问题

问题核心

基于.NET 10搭建的Blazor身份认证项目,将AppDbContext迁移至独立类库后,新生成的EF Core迁移中缺失AspNetUserPasskeys表,尽管已配置IdentityOptions.Stores.SchemaVersion = IdentitySchemaVersions.Version3。

解决方案步骤

1. 修正设计时工厂的服务注册逻辑

之前的代码存在服务提供器构建顺序错误,且未显式启用Passkey存储支持。以下是修正后的DesignTimeDbContextFactory:

public sealed class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
    public AppDbContext CreateDbContext(string[] args)
    {
        var connectionString = Environment.GetEnvironmentVariable("ConnectionStrings__Default");
        if (string.IsNullOrWhiteSpace(connectionString))
        {
            throw new InvalidOperationException(
                "Missing env var 'ConnectionStrings__Default' for design-time DbContext creation.");
        }

        // 构建完整服务集合
        var services = new ServiceCollection();

        // 添加选项服务
        services.AddOptions();

        // 统一配置Identity选项
        services.Configure<IdentityOptions>(o =>
        {
            o.Stores.SchemaVersion = IdentitySchemaVersions.Version3;
            o.SignIn.RequireConfirmedAccount = true;
            o.User.RequireUniqueEmail = true;
            o.Password.RequiredLength = 8;
            o.Password.RequireNonAlphanumeric = false;
            o.Password.RequireUppercase = false;
            o.Password.RequireLowercase = true;
            o.Password.RequireDigit = true;
        });

        // 添加EF Core数据库服务(根据你的数据库类型调整,这里用Npgsql)
        services.AddEntityFrameworkNpgsql();

        // 添加Identity核心服务并显式启用Passkey存储
        services.AddIdentityCore<ApplicationUser>()
            .AddEntityFrameworkStores<AppDbContext>()
            .AddSignInManager()
            .AddDefaultTokenProviders()
            .AddPasskeyStore(); // 关键:启用Passkey存储实体配置

        // 最后构建服务提供器
        var serviceProvider = services.BuildServiceProvider();

        // 配置DbContext选项
        var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>()
            .UseNpgsql(connectionString)
            .UseInternalServiceProvider(serviceProvider);

        return new AppDbContext(optionsBuilder.Options, new DesignTimeTenantProvider());
    }

    private sealed class DesignTimeTenantProvider : ITenantProvider
    {
        public Guid OrganizationId => Guid.Empty;
        public bool HasTenant => false;
    }
}

2. 确保AppDbContext正确应用Passkey模型配置

在AppDbContext的OnModelCreating方法中,显式应用Passkey实体配置(可选但能避免自动配置失效):

public class AppDbContext : IdentityDbContext<ApplicationUser>
{
    private readonly ITenantProvider tenantProvider;

    // 运行时构造函数
    public AppDbContext(DbContextOptions<AppDbContext> options, ITenantProvider tenantProvider)
        : base(options)
    {
        this.tenantProvider = tenantProvider;
    }

    // 设计时构造函数
    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options)
    {
        this.tenantProvider = new DesignTimeTenantProvider();
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        // 手动应用Passkey实体配置,确保模型包含AspNetUserPasskeys表
        builder.ApplyConfiguration(new IdentityUserPasskeyConfiguration<ApplicationUser>());
    }

    private sealed class DesignTimeTenantProvider : ITenantProvider
    {
        public Guid OrganizationId => Guid.Empty;
        public bool HasTenant => false;
    }
}

3. 重新生成迁移并更新数据库

执行以下命令完成迁移操作:

  • 清理现有冲突迁移(如有需要):dotnet ef migrations remove
  • 创建新迁移:dotnet ef migrations add AddPasskeyTable
  • 更新数据库:dotnet ef database update

问题原因解析

  1. 服务注册顺序错误:原代码在添加IdentityCore服务前就构建了服务提供器,导致Passkey存储配置未被纳入EF Core的模型构建流程。
  2. 缺少Passkey存储启用:必须显式调用.AddPasskeyStore(),Identity才会自动注册AspNetUserPasskeys表的实体配置,仅设置SchemaVersion不足以触发该逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 14:53:10