我有ASP.NET MVC 5网站的默认项目模板,我试图列出具有角色名称(而不是ID)的所有用户.
查询是:
db.Users.Include(u => u.Roles).ToList()
然后我想用以下内容打印角色名称:
@string.Join(", ", user.Roles.Select(r => r.RoleId))
问题是我只能访问RoleId
,而不是Name
存储其他属性的Role类.
我可以运行另一个select来获取所有角色,然后将其用作查找.或者直接在查询中写一个连接?我不知道是怎么回事,因为我无法访问IdentityUserRole
具有绑定用户和角色的实体的表.
问题的根源似乎是Roles集合IdentityUserRole
(非Role
)仅包含RoleId
和UserId
.
public class IdentityUserRole{ public virtual TKey RoleId { get; set; } public virtual TKey UserId { get; set; } }
我想如果想要在EF中做N对N关系,他们应该直接收集Roles
然后覆盖OnModelCreating
并指定关系.这种方法似乎使从一个对象浏览对象变得复杂.
为什么他们决定将其IdentityUserRole
作为额外的实 能够在关系中添加额外数据吗?代价是无法从用户导航到角色?
我这样做的方式是:
using (var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationContext())) { var rolesForUser = await userManager.GetRolesAsync(userId); // rolesForUser now has a list role classes. }
身份团队制作了两个经理:RoleManager
用于整理角色(尽管不是用户角色),UserManager
基本上用于所有身份验证.还有一个SignInManager
,但不是必需的.
因此UserManager
找到用户,创建用户,删除用户,发送电子邮件....列表继续.
所以我Action
看起来像这样:
public async Task<ActionResult> GetRolesForUser(string userId) { using ( var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()))) { var rolesForUser = await userManager.GetRolesAsync(userId); return this.View(rolesForUser); } }
要执行原始SQL,您可以执行以下操作:
根据查询的输出创建Entity Framework可以映射到的类:
public class UserWithRole { public string UserName {get;set;} // You can alias the SQL output to give these better names public string Name {get;set;} } using (var context = new DbContext()) { var sql = @" SELECT AspNetUsers.UserName, AspNetRoles.Name FROM AspNetUsers LEFT JOIN AspNetUserRoles ON AspNetUserRoles.UserId = AspNetUsers.Id LEFT JOIN AspNetRoles ON AspNetRoles.Id = AspNetUserRoles.RoleId WHERE AspNetUsers.Id = @Id"; var idParam = new SqlParameter("Id", theUserId); var result = context.Database.ExecuteQuery<UserWithRole>(sql, idParam); }
很简单!
如果您为SQL返回列添加别名:
SELECT AspNetUSers.UserName, AspNetRoles.Name As RoleName
然后你的DTO类看起来像这样:
public class UserWithRole { public string UserName {get;set;} public string RoleName {get;set;} }
这显然更清洁了.