ASP.NET身份验证:获取某个角色中的所有用户

13
如何获得角色中所有用户的列表?在之前可以使用Roles.GetUsersInRole,但是在新的Identity中我找不到类似的东西。

1
发现角色成员可能是极其昂贵的,包括对支持接受身份的实际数据存储进行重复远程查询 - 即使这些存储支持此类查询。尝试将事物颠倒过来 - 为什么需要知道角色的所有成员?(请记住,一旦系统获得此信息,它可能已经过时) - Damien_The_Unbeliever
1
@Damien_The_Unbeliever:我需要将一个应用程序从旧的Membership迁移到新的Identity。例如,我需要有一个管理员角色用户列表,以便向他们所有人发送电子邮件。现在我正在尝试想象一个数据库查询,并且看起来这是一个带有一个内部连接的简单查询。也许我错过了很多东西,但我不明白为什么这非常昂贵。所以,我总是可以通过db context来完成这个操作,但只是想知道为什么框架不提供这个功能。 - graycrow
我说它可能会很昂贵 - 并非所有使用身份验证系统的情况下都将角色存储在SQL数据库中。 - Damien_The_Unbeliever
7个回答

12

我没有看到内置的方法,但是实现起来相当容易。我在我的应用程序特定的UserManager中有这种方法:

public IQueryable<User> GetUsersInRole(string roleName)
{
    return from user in Users
           where user.Roles.Any(r => r.Role.Name == roleName)
           select user;
}

它输出的SQL语句看起来很合理:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Email] AS [Email], 
[Extent1].[EmailConfirmed] AS [EmailConfirmed], 
[Extent1].[PasswordHash] AS [PasswordHash], 
[Extent1].[SecurityStamp] AS [SecurityStamp], 
[Extent1].[PhoneNumber] AS [PhoneNumber], 
[Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed], 
[Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled], 
[Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc], 
[Extent1].[LockoutEnabled] AS [LockoutEnabled], 
[Extent1].[AccessFailedCount] AS [AccessFailedCount], 
[Extent1].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent1]
WHERE  EXISTS (SELECT 
    1 AS [C1]
    FROM  [dbo].[AspNetUserRoles] AS [Extent2]
    INNER JOIN [dbo].[AspNetRoles] AS [Extent3] ON [Extent2].[RoleId] = [Extent3].[Id]
    WHERE ([Extent1].[Id] = [Extent2].[UserId]) AND ([Extent3].[Name] = @p__linq__0)
)

11

由于某些原因,@ChoptimusPrime提出的非常好的查询在我的ASP.NET Identity 2.2.1中没有编译。我写了一个扩展函数:

public static IQueryable<User> GetUsersInRole(DbContext db, string roleName)
{
  if (db != null && roleName != null)
  {
    var roles = db.Roles.Where(r => r.Name == roleName);
    if (roles.Any())
    {
      var roleId = roles.First().Id;
      return from user in db.Users
             where user.Roles.Any(r => r.RoleId == roleId)
             select user;
    }
  }
  return null;
}

5
例如,如果您想获取具有“用户”角色的用户列表。
var users = await (from user in _dbContext.Users
                                 join userRole in _dbContext.UserRoles
                                 on user.Id equals userRole.UserId
                                 join role in _dbContext.Roles 
                                 on userRole.RoleId equals role.Id
                                 where role.Name == "User" 
                                 select user)
                                 .ToListAsync();

4

在1.0 RTM中,无法通过RoleManager实现此功能,但在1.1中,可以通过IQueryable RoleManager.Roles实现。对于1.0版本,您需要降到实现层(即数据库上下文)。


你能解释一下吗?给我们一些代码或示例。谢谢。 - Kamran Sadin

0

你可以使用Entity Framework,但是在Asp.Net Identity 1.0中还不可能。你必须等待Identity 2.0的发布。

using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings("DefaultConnection").ConnectionString)) {
    string queryString = "SELECT AspNetUsers.UserName FROM dbo.AspNetUsers INNER JOIN dbo.AspNetUserRoles ON " + "AspNetUsers.Id=AspNetUserRoles.UserId WHERE AspNetUserRoles.RoleID='" + id + "'";
    SqlCommand command = new SqlCommand(queryString, connection);
    command.Connection.Open();

    List<string> @out = null;
    dynamic reader = command.ExecuteReader();
    while (reader.Read()) {
        if (@out == null) @out = new List<string>();
        @out.Add(reader.GetString(0));
    }

    return @out;
}

最好使用带有Identity的Entity Framework,而不是降级到SqlConnection和SqlCommands。在我看来。 - Sean Newcome

0

获取任何角色中的用户的最简单方法

int totalUser=db.AspNetUsers.Where(u => u.AspNetRoles.Any(r => r.Name == "USER")).Count()

0

这是针对新的MVC 5 ASP.NET Identity

var managerRole = TMRoles.GetIdentityRole(TMRoles.Manager);
var managers = managerRole.Users;

public class TMRoles
{
    private static RoleManager<IdentityRole> RoleManager = 
        new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new TMContext()));

    public static string Manager { get { return "Manager"; } }


    public static IdentityRole GetIdentityRole(string roleName)
    {
        return RoleManager.FindByName(roleName);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接