问题描述
我有 ASP.NET MVC 5 网站的默认项目模板,我正在尝试列出所有具有角色名称(而不是 ID)的用户.
I have default project template of ASP.NET MVC 5 web site and I am trying to list all users with role names (not IDs).
查询是:
db.Users.Include(u => u.Roles).ToList()
然后我想用类似这样的方式打印角色名称:
Then I want to print the role names with something like:
@string.Join(", ", user.Roles.Select(r => r.RoleId))
问题是我只能访问 RoleId
,而不是存储 Name
和其他属性的 Role 类.
The problem is that I can reach only RoleId
, not Role class where Name
and other properties are stored.
我可以运行另一个选择来获取所有角色,然后将其用作查找.还是直接在查询中写一个join?我不知道怎么做,因为我无法访问带有将用户和角色绑定在一起的 IdentityUserRole
实体的表.
I could run another select to get all roles and then use that as a lookup. Or write a join in the query directly? I am not sure how because I do not have access to the table with IdentityUserRole
entities that are binding users and roles together.
问题的根源似乎是 IdentityUserRole
(不是 Role
)的 Roles 集合,它只包含 RoleId
和 UserId
.
The root of the problem seems to be the fact that is Roles collection of IdentityUserRole
(not Role
) which contains only RoleId
and UserId
.
public class IdentityUserRole<TKey> {
public virtual TKey RoleId { get; set; }
public virtual TKey UserId { get; set; }
}
我认为如果想在 EF 中建立 N 对 N 关系,他们应该直接放置 Roles
集合,然后覆盖 OnModelCreating
并指定关系.这种方法似乎使从一个对象浏览到另一个对象变得复杂.
I thought that if one want to do N-to-N relationship in EF they should put directly collection of Roles
and then override OnModelCreating
and specify the relationships. This approach seems to complicate browsing the objects from one to another.
为什么他们决定将 IdentityUserRole
作为额外实体包含在内?为了能够向关系添加额外的数据?以无法从用户导航到角色为代价?
Why they decided to include IdentityUserRole
as extra entity? To be able to add extra data to the relationships? At cost of not being able to navigate from users to roles?
推荐答案
我的做法是:
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
,但不是必需的.
The identity team made two managers: RoleManager
for sorting out roles (not user roles though) and UserManager
basically for everything authentication wise. There is also a SignInManager
as well but not needed.
所以 UserManager
查找用户、创建用户、删除用户、发送电子邮件....这样的例子不胜枚举.
So UserManager
finds users, creates users, deletes users, sends emails .... the list goes on.
所以我的 Action
可能看起来像这样:
So my Action
could look like this:
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,您可以执行以下操作:
To execute raw SQL then you can do something like this:
根据查询的输出创建实体框架可以映射到的类:
Create the class that Entity Framework can map to, based on the output of your query:
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 返回列添加别名:
If you alias your SQL return columns:
SELECT AspNetUSers.UserName, AspNetRoles.Name As RoleName
那么你的 DTO 类可以如下所示:
Then your DTO class can look like this:
public class UserWithRole
{
public string UserName {get;set;}
public string RoleName {get;set;}
}
这显然要干净得多.
这篇关于如何在 ASP.NET MVC 5 中列出具有角色名称的用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!