如何查询拥有特定声明的角色及IdentityRole导航属性外键配置问题
实现方案及问题修复
1. 关联查询直接声明+角色间接声明的用户
你可以通过两步查询合并结果实现需求,以下是基于DbContext的高效实现方案:
- 第一步:查询所有携带目标声明的角色ID列表
- 第二步:查询所有属于上述角色的用户ID,再合并直接持有目标声明的用户ID,去重后得到最终结果
示例代码如下:
public async Task<List<ApplicationUser>> GetAllUsersWithClaimAsync(string claimType, string claimValue) { // 查询携带目标声明的角色ID var roleIds = await context.RoleClaims .Where(rc => rc.ClaimType == claimType && rc.ClaimValue == claimValue) .Select(rc => rc.RoleId) .ToListAsync(); // 查询属于上述角色的用户ID var userIdsFromRole = await context.UserRoles .Where(ur => roleIds.Contains(ur.RoleId)) .Select(ur => ur.UserId) .ToListAsync(); // 查询直接持有目标声明的用户ID var userIdsFromClaim = await context.UserClaims .Where(uc => uc.ClaimType == claimType && uc.ClaimValue == claimValue) .Select(uc => uc.UserId) .ToListAsync(); // 合并去重后查询用户实体 var allUserIds = userIdsFromRole.Union(userIdsFromClaim).Distinct().ToList(); return await context.Users.Where(u => allUserIds.Contains(u.Id)).ToListAsync(); }
如果不想直接操作DbContext,也可以组合roleManager.GetClaimsAsync、userManager.GetUsersInRoleAsync等内置方法实现,但性能会比直接联查低。
2. 自定义角色Claims导航属性外键配置
报错是因为EF Core默认会按你的自定义角色类名ApplicationRole生成外键名ApplicationRoleId,但Identity自带的角色声明表的外键列实际为RoleId,只需要在OnModelCreating方法中显式配置一对多关系即可:
protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // 配置ApplicationRole和RoleClaim的关联关系 builder.Entity<ApplicationRole>() .HasMany(r => r.Claims) .WithOne() .HasForeignKey(rc => rc.RoleId) .IsRequired() .OnDelete(DeleteBehavior.Cascade); }
同时注意你的自定义DbContext需要正确传入自定义角色的泛型参数:
// TContext的泛型参数依次为 用户类型、角色类型、主键类型 public class AppDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string> { // 上下文构造函数等逻辑 }
配置完成后重新执行迁移即可,不需要加[ForeignKey]属性。
内容的提问来源于stack exchange,提问作者SamWM
相关产品推荐
相关产品推荐

