如何在无导航属性时通过单次查询获取所有用户及关联角色?
解决方案:单次查询获取所有用户及其角色
方法一:添加导航属性(推荐)
默认的ApplicationUser和UserRole确实没有自带这些导航属性,你可以手动添加并配置关系,这样就能用简洁的LINQ查询实现需求。
修改实体类
- 在
ApplicationUser中添加用户角色关联集合:public class ApplicationUser : IdentityUser { // 其他已有属性 public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; } = new List<IdentityUserRole<string>>(); } - 如果使用自定义
UserRole类(继承自IdentityUserRole<string>),添加角色导航属性:public class UserRole : IdentityUserRole<string> { public virtual IdentityRole<string> Role { get; set; } }
- 在
在DbContext中配置关系
重写OnModelCreating方法,配置实体间的关联:protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // 配置用户与用户角色的一对多关系 builder.Entity<ApplicationUser>() .HasMany(u => u.UserRoles) .WithOne() .HasForeignKey(ur => ur.UserId) .IsRequired(); // 配置用户角色与角色的一对一关系 builder.Entity<UserRole>() .HasOne(ur => ur.Role) .WithMany(r => r.UserRoles) .HasForeignKey(ur => ur.RoleId) .IsRequired(); }调整LINQ查询
现在你的第一种查询可以正常运行,只需加上导航属性的加载:Users = await (from u in DbContext.Users.Include(u => u.UserRoles).ThenInclude(ur => ur.Role) orderby u.Name select new UserSummaryViewModel { Id = u.Id, Name = u.Name, Roles = u.UserRoles.Select(ur => ur.Role.Name) }) .ToListAsync();
方法二:手动关联表(无需修改实体)
如果无法修改现有实体类,直接通过Join关联Users、UserRoles、Roles三张表,再分组聚合每个用户的角色:
Users = await (from u in DbContext.Users join ur in DbContext.UserRoles on u.Id equals ur.UserId join r in DbContext.Roles on ur.RoleId equals r.Id orderby u.Name group r.Name by new { u.Id, u.Name } into userRolesGroup select new UserSummaryViewModel { Id = userRolesGroup.Key.Id, Name = userRolesGroup.Key.Name, Roles = userRolesGroup.ToList() }) .ToListAsync();
关于默认导航属性的说明
微软Identity框架默认不提供这些导航属性,是为了保持实体的轻量性——毕竟不是所有业务场景都需要直接关联用户与角色。开发者可以根据自身业务需求,自行扩展实体并配置关联关系。
内容的提问来源于stack exchange,提问作者Jonathan Wood
相关产品推荐
相关产品推荐

