身份 2.2.1 中具有角色列表的用户列表

List of Users with list of Roles in Identity 2.2.1

所以我一直在搜索 Google 等等。感觉这个问题已经被问过很多次了,但没有答案对我有帮助,但我觉得我已经接近了。但是,我是 LINQ 和 Lambda 的新手,不具备做我想做的事情的知识。

想要的结果

User                   Roles
-----------------------------------------
John                   Admin
Jane                   Staff, HR, Payroll
MyCoolUserName         User

我离 and this post 很近了。这是我到目前为止得到的。

视图模型:

public class UsersViewModel {
    [Display(Name = "User")]
    public ApplicationUser User { get; set; }

    [Display(Name = "Roles")]
    public string Roles { get; set; }
}

控制器:

试验#1

此解决方案 returns 角色空白,我必须将其添加到我的 web.config 文件中:<roleManager enabled="true" />

public class UsersController : Controller {
    public async Task Index() {
        var allUsers = await db.Users.ToListAsync();
        var users = new List();
        foreach (var user in allUsers) {
            String[] roles = Roles.GetRolesForUser(user.UserName);
            users.Add(new UsersViewModel {User = u, Roles = String.Join(",", roles.ToArray())});
        }
        return View(users);
    }
}

试验 #2

此解决方案 returns 每个用户每个角色一行,但只有 returns RoleId

public class UsersController : Controller {
    public async Task Index() {
        var allUsers = await db.Users.ToListAsync();
        var users = allUsers.Select(u => new UsersViewModel {User = u, Roles = String.Join(",", u.Roles.Select(r => r.RoleId))}).ToList();
        return View(users);
    }
}

以下是我将 RoleId 更改为 RoleName 后在试用 #2 中得到的结果:

我可以看出在试验 #2 中,u.Roles 链接到 UserRoles table。从逻辑上讲,我知道我想要的是内部加入 Roles table 并在那里获取名称。

我希望有人能帮助我吗?提前致谢。 Sample Project

您不需要在 LINQ 查询中执行联接,因为 UserRole 只是 User 的 导航 属性 (因此它们将由 EF 自动映射)。唯一需要记住的是,如果禁用延迟加载,则需要手动调用 Include(entity) 将实体加载到查询中。

代码示例:

如果您禁用 "Lazy Loading":

public class UsersController : Controller {
    public async Task Index() {
        var users = allUsers.Include(Roles).Select(u => new UserViewModel {UserName = u.UserName, Roles = String.Join(",", u.Roles.Select(r => r.RoleName))}).ToList();
        return View(users);
    }
}

如果您启用 "Lazy Loading":

public class UsersController : Controller {
    public async Task Index() {
        var users = allUsers.Select(u => new UserViewModel {UserName = u.UserName, Roles = String.Join(",", u.Roles.Select(r => r.RoleName))}).ToList();
        return View(users);
    }
}

更新: 我还没有看到您的模型 类,但我认为您有 3 个模型 类(用户、角色、用户角色),因为用户和角色具有 多对多关系(如您的 gif 所示,角色只有 UserId 和 RoleId)。

public class UsersController : Controller {
    public async Task Index() {
        var users = allUsers.Select(u => new UserViewModel {UserName = u.UserName, Roles = String.Join(",", u.UserRoles.Where(userRole => u.Roles.Select(r => r.RoleId).Contains(userRole.Id)).Select(userRole => userRole.Name)}).ToList();
        return View(users);
    }
}

感谢@Kienct89 和我们的讨论,我自己偶然发现了答案。这是我得到的,如果有人可以或想要改进它,请这样做。

例如:我不知道首先将所有角色放入一个变量并对其进行迭代是否更好,您在版本 1 中看到了这一点,或者在版本 2 中看到了这一点。

版本 1

public class UsersController : Controller {
    public async Task Index() {
        var allUsers = await db.Users.ToListAsync();
        var users = allUsers.Select(u => new UsersViewModel {User = u, Roles = String.Join(",", db.Roles.Where(role => role.Users.Any(user => user.UserId == u.Id)).Select(r => r.Name))}).ToList();
        return View(users);
    }
}

版本 2(首选?)

public class UsersController : Controller {
    public async Task Index() {
        var allUsers = await db.Users.ToListAsync();

        // set all roles to a variable, so that we don't hit the database for every user iteration
        // is this true?
        var allRoles = await db.Roles.ToListAsync();

        var users = allUsers.Select(u => new UsersViewModel {User = u, Roles = String.Join(",", allRoles.Where(role => role.Users.Any(user => user.UserId == u.Id)).Select(r => r.Name))}).ToList();
        return View(users);
    }
}

我觉得 版本 2 效率更高,因为它不会访问数据库来获取每个用户的角色。相反,它具有变量中的角色。我不确定我是否正确,但我想得到启发并向任何知道的人学习。