重命名数据库表后Owin Identity Framework无法返回Claims的问题求助
解决ASP.NET 4.6.1 MVC重命名Identity表后无法获取Claims的问题
这个问题我之前帮同事排查过,核心原因很明确:你重写OnModelCreating时只配置了用户表的重命名,漏掉了用户声明(UserClaims)表的EF映射配置,导致EF查询Claims时依然去查默认的AspNetUserClaims表,而你的实际数据存在重命名后的新表里,自然读不到数据。
问题分析
ASP.NET Identity的默认表结构包含多个关联表(用户、角色、用户声明、用户角色关联等),当你重写OnModelCreating自定义表名时,只修改ApplicationUser的表名是不够的。UserManager.AddClaim之所以能成功把数据写入新表,大概率是你手动修改了数据库表名,但EF的实体映射还停留在默认表名上——读写操作的映射不匹配,就出现了“写得进但读不出”的诡异情况。
解决方案:完整配置所有Identity表的映射
在OnModelCreating方法中,必须为所有Identity相关实体指定重命名后的表名,而且一定要先调用base.OnModelCreating(modelBuilder)(否则Identity的默认映射会被覆盖,导致关联关系失效)。
示例代码如下(假设你把表名统一改成简洁的命名):
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // 先调用base方法,初始化Identity的默认映射规则 base.OnModelCreating(modelBuilder); // 重命名用户表 modelBuilder.Entity<ApplicationUser>().ToTable("Users"); // 重命名角色表 modelBuilder.Entity<IdentityRole>().ToTable("Roles"); // 关键:配置用户声明表的新名称(这一步你肯定漏掉了!) modelBuilder.Entity<IdentityUserClaim<string>>().ToTable("UserClaims"); // 其他关联表如果也重命名了,也要同步配置 modelBuilder.Entity<IdentityUserRole<string>>().ToTable("UserRoles"); modelBuilder.Entity<IdentityUserLogin<string>>().ToTable("UserLogins"); modelBuilder.Entity<IdentityRoleClaim<string>>().ToTable("RoleClaims"); }
注意事项
- 主键类型匹配:如果你的Identity主键不是默认的
string(比如用int),要把泛型参数改成对应类型,比如IdentityUserClaim<int>。 - 自定义Claim实体的情况:如果你创建了自定义的
ApplicationUserClaim类,需要在DbContext的泛型参数中指定它,同时添加对应的映射:// 自定义Claim实体 public class ApplicationUserClaim : IdentityUserClaim<string> { // 你的自定义属性 } // 自定义DbContext,指定泛型参数 public class ApplicationDbContext : IdentityDbContext<ApplicationUser, IdentityRole, string, ApplicationUserClaim, IdentityUserRole<string>, IdentityUserLogin<string>, IdentityRoleClaim<string>, IdentityUserToken<string>> { public ApplicationDbContext() : base("DefaultConnection") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<ApplicationUserClaim>().ToTable("UserClaims"); // 其他表配置... } } - 验证查询SQL:可以开启EF的日志功能,或者用SQL Server Profiler查看生成的查询语句,确认EF是否在查询你重命名后的表。
按这个配置修改后,再调用UserManager.GetClaimsAsync就能正确读取到数据库里的Claims了。
内容的提问来源于stack exchange,提问作者Slipped
相关产品推荐
相关产品推荐

