ASP.NET Core Identity加载用户声明:为何无法用Include关联查询?
解决Identity用户与声明关联查询的问题
当你的DbContext继承IdentityDbContext<User>时,默认确实没有给User实体配置UserClaims的导航属性,所以直接用Include(u => u.UserClaims)会编译失败;而智能感知能识别的u.Claims其实是IdentityUser的扩展方法,不是实体的导航属性,自然不能用于Include操作。
不用每次执行两次查询,有几种更简洁的处理方式:
1. 给自定义User实体添加导航属性并配置关系
如果想通过Include实现关联查询,可以给你的User类添加导航属性,然后在DbContext中配置EF的一对多关系:
首先修改User实体:
public class User : IdentityUser<string> { // 添加用户声明的导航属性 public virtual ICollection<IdentityUserClaim<string>> UserClaims { get; set; } = new List<IdentityUserClaim<string>>(); }
然后在DbContext的OnModelCreating方法中补充关系配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 配置用户与声明的一对多关联 modelBuilder.Entity<User>() .HasMany(u => u.UserClaims) .WithOne() .HasForeignKey(uc => uc.UserId) .IsRequired(); }
配置完成后,就可以用Include一次性查询用户和对应声明:
User jim = await Context.Users .Include(u => u.UserClaims) .SingleAsync(u => u.UserName == "Jim");
2. 使用投影查询一次获取数据
如果不想修改实体和配置,可以直接用EF的投影查询,通过一次数据库请求同时获取用户和声明:
var jimWithClaims = await Context.Users .Where(u => u.UserName == "Jim") .Select(u => new { User = u, Claims = Context.UserClaims.Where(uc => uc.UserId == u.Id).ToList() }) .SingleAsync(); // 从结果中提取数据:jimWithClaims.User 是用户对象,jimWithClaims.Claims 是对应声明列表
3. 使用Identity的UserManager内置方法
如果项目中使用了ASP.NET Identity的UserManager,可以直接调用它的GetClaimsAsync方法,内部会自动处理关联查询:
// 依赖注入UserManager<User> private readonly UserManager<User> _userManager; // 在业务方法中调用 User jim = await _userManager.FindByNameAsync("Jim"); var claims = await _userManager.GetClaimsAsync(jim);
内容的提问来源于stack exchange,提问作者DreamingOfSleep
相关产品推荐
相关产品推荐

