.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
问题原因解析
- 服务注册顺序错误:原代码在添加IdentityCore服务前就构建了服务提供器,导致Passkey存储配置未被纳入EF Core的模型构建流程。
- 缺少Passkey存储启用:必须显式调用
.AddPasskeyStore(),Identity才会自动注册AspNetUserPasskeys表的实体配置,仅设置SchemaVersion不足以触发该逻辑。
内容的提问来源于stack exchange,提问作者Artur Michajluk
相关产品推荐
相关产品推荐

