繁体   English   中英

.NET 核心 2.1 身份获取所有用户及其相关角色

[英].NET Core 2.1 Identity get all users with their associated roles

我正在尝试为用户管理管理页面提取我所有的身份用户及其相关角色。 我认为这会相当容易,但显然不是。 我尝试了以下解决方案: https://stackoverflow.com/a/43562544/5392786但到目前为止还没有解决。

这是我到目前为止所拥有的:

应用用户:

public class ApplicationUser : IdentityUser
{
    public List<IdentityUserRole<string>> Roles { get; set; }
}

数据库环境

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

启动标识代码

services.AddIdentity<ApplicationUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

Razor 我要显示列表的页面:

public class IndexModel : PageModel
{
    private readonly UserManager<ApplicationUser> userManager;

    public IndexModel(UserManager<ApplicationUser> userManager)
    {
        this.userManager = userManager;
    }

    public IEnumerable<ApplicationUser> Users { get; set; }

    public void OnGetAsync()
    {
        this.Users = userManager.Users.Include(u => u.Roles).ToList();
    }
}

调用userManager.Users.Include(u => u.Roles).ToList();时出现以下错误 :

MySql.Data.MySqlClient.MySqlException:'字段列表'中的未知列'u.Roles.ApplicationUserId''

我现在已经实施了以下解决方案。

正如 CodeNotFound 在评论中指出的那样, IdentityUser 曾经有一个Roles属性。 在 .NET Core 中不再是这种情况。 GitHub 上的这个评论/问题似乎是 .Net Core 的当前解决方案。 我试图用以下代码实现它:

应用用户

public class ApplicationUser : IdentityUser
{
    public ICollection<ApplicationUserRole> UserRoles { get; set; }
}

应用用户角色

public class ApplicationUserRole : IdentityUserRole<string>
{
    public virtual ApplicationUser User { get; set; }
    public virtual ApplicationRole Role { get; set; }
}

应用角色

public class ApplicationRole : IdentityRole
{
    public ICollection<ApplicationUserRole> UserRoles { get; set; }
}

数据库上下文

public class ApplicationDbContext
    : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserClaim<string>,
    ApplicationUserRole, IdentityUserLogin<string>,
    IdentityRoleClaim<string>, IdentityUserToken<string>>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<ApplicationUserRole>(userRole =>
        {
            userRole.HasKey(ur => new { ur.UserId, ur.RoleId });

            userRole.HasOne(ur => ur.Role)
                .WithMany(r => r.UserRoles)
                .HasForeignKey(ur => ur.RoleId)
                .IsRequired();

            userRole.HasOne(ur => ur.User)
                .WithMany(r => r.UserRoles)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();
        });
    }
}

启动

services.AddIdentity<ApplicationUser, ApplicationRole>(options => options.Stores.MaxLengthForKeys = 128)
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

最后,确保在使用它时急切地加载 User 的 UserRoles,然后加载 UserRole 的 Role,如下所示:

this.Users = userManager.Users.Include(u => u.UserRoles).ThenInclude(ur => ur.Role).ToList();

我有一个问题,其中每个UserRoleRole属性为空,这通过添加.ThenInclude(ur => ur.Role)部分解决了。

关于多级急切加载的 Microsoft 文档: https : //docs.microsoft.com/en-us/ef/core/querying/related-data#include-multiple-levels

ASP 核心 2.2 更新

继承自IdentityUserRole<Guid>不是字符串 您可能还需要删除模型构建器中的代码才能使迁移工作。

对于 dotnet core 3.1,我一直在使用以下通用方法。

// _appContext is an instance of IdentityDbContext<ApplicationUser>

_appContext.Users
.SelectMany(
    // -- below emulates a left outer join, as it returns DefaultIfEmpty in the collectionSelector
    user => _appContext.UserRoles.Where(userRoleMapEntry => user.Id == userRoleMapEntry.UserId).DefaultIfEmpty(),
    (user, roleMapEntry) => new { User = user, RoleMapEntry = roleMapEntry })
.SelectMany(
    // perform the same operation to convert role IDs from the role map entry to roles
    x => _appContext.Roles.Where(role => role.Id == x.RoleMapEntry.RoleId).DefaultIfEmpty(),
    (x, role) => new {User = x.User, Role = role})
.ToList() // runs the queries and sends us back into EF Core LINQ world
.Aggregate(
    new Dictionary<ApplicationUser, List<IdentityRole>>(), // seed
    (dict, data) => {
        // safely ensure the user entry is configured
        dict.TryAdd(data.User, new List<IdentityRole>());
        if (null != data.Role)
        {
            dict[data.User].Add(data.Role);
        }
        return dict;
    },
    x => x);

生成的 SQL 简单而合理:

SELECT "a"."Id", 
"a"."AccessFailedCount", 
"a"."ConcurrencyStamp", 
"a"."Email", 
"a"."EmailConfirmed", 
"a"."LockoutEnabled", 
"a"."LockoutEnd", 
"a"."NormalizedEmail", 
"a"."NormalizedUserName", 
"a"."PasswordHash", 
"a"."PhoneNumber", 
"a"."PhoneNumberConfirmed", 
"a"."SecurityStamp", 
"a"."TwoFactorEnabled", 
"a"."UserName", 
"a1"."Id", 
"a1"."ConcurrencyStamp", 
"a1"."Name", 
"a1"."NormalizedName"
FROM "AspNetUsers" AS "a"
LEFT JOIN "AspNetUserRoles" AS "a0" ON "a"."Id" = "a0"."UserId"
LEFT JOIN "AspNetRoles" AS "a1" ON "a0"."RoleId" = "a1"."Id"

通过调用 _userManager.GetRolesAsync(user) 函数遍历用户列表并获取用户角色,并在一个字符串变量中遍历用户角色并使用“,”拆分角色

[HttpPost]
    public async Task<IActionResult> OnPostGetPagination()
    {


        var users = await _userManager.Users.ToListAsync();
        InputModel inputModel = new InputModel();
        foreach (var v in users)
        {
            inputModel = new InputModel();
            var roles = await _userManager.GetRolesAsync(v);
            inputModel.Email = v.UserName;
            inputModel.role = "";
            foreach (var r in roles)
            {
                if (!inputModel.role.Contains(","))
                {
                    inputModel.role = r;
                }
                else
                {
                    inputModel.role = "," + r;
                }
            }
            Input2.Add(inputModel);
        }


    }

祝你好运

参考评论

首先是获取数据的代码

 public async Task<IEnumerable<AccountViewModel>> GetUserList()
        {
            var userList = await (from user in _context.Users
                                  select new
                                  {
                                      UserId = user.Id,
                                      Username = user.UserName,
                                      user.Email,
                                      user.EmailConfirmed,
                                      RoleNames = (from userRole in user.Roles //[AspNetUserRoles]
                                                   join role in _context.Roles //[AspNetRoles]//
                                                   on userRole.RoleId
                                                   equals role.Id
                                                   select role.Name).ToList()
                                  }).ToListAsync();

            var userListVm = userList.Select(p => new AccountViewModel
            {
                UserId = p.UserId,
                UserName = p.Username,
                Email = p.Email,
                Roles = string.Join(",", p.RoleNames),
                EmailConfirmed = p.EmailConfirmed.ToString()
            });

            return userListVm;
        }

在 ASP.Net core 2.1 中,我们像这样设置 ApplicationRole 以获取用户的角色。 您需要定义要显式公开供用户使用的数据

public class ApplicationRole : IdentityRole
    {
        public virtual ICollection<IdentityUserRole<string>> Users { get; set; }

        public virtual ICollection<IdentityRoleClaim<string>> Claims { get; set; }
    }

最后

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
            {
                relationship.DeleteBehavior = DeleteBehavior.Restrict;
            }

            modelBuilder.Entity<User>().HasMany(u => u.Claims).WithOne().HasForeignKey(c => c.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
            modelBuilder.Entity<User>().HasMany(u => u.Roles).WithOne().HasForeignKey(r => r.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);

            modelBuilder.Entity<ApplicationRole>().HasMany(r => r.Claims).WithOne().HasForeignKey(c => c.RoleId).IsRequired().OnDelete(DeleteBehavior.Cascade);
            modelBuilder.Entity<ApplicationRole>().HasMany(r => r.Users).WithOne().HasForeignKey(r => r.RoleId).IsRequired().OnDelete(DeleteBehavior.Cascade);

            modelBuilder.EnableAutoHistory(null);
        }

结果将是用户名和用户角色。 如果用户有 1 个以上的角色,则数据将显示为管理员、编辑器等...

完整的代码可以在这里找到这里这里希望这有帮助。

由于这是 google 搜索结果的顶部; 现在你可以加入 UserRoles dbset(如果你的 db 上下文继承自 IdentityDbContext)。

例如,将角色表外部连接到任何用户角色,然后创建我们的 manageUserModel(为我们的 api 减少 applicationUser 类的信息):

var employees = (from bb in _appContext.Users
            join roleIds in _appContext.UserRoles on bb.Id equals roleIds.UserId
            join role in _appContext.Roles on roleIds.RoleId equals role.Id into roles
            orderby bb.LastName, bb.FirstName
            where roles !=null && roles.Any(e => e.Name == Permissions.RoleNames.Administrator || e.Name == Permissions.RoleNames.Employee)
            select ManageUserModel.FromInfo(bb, roles)).ToList();

public static ManageUserModel FromInfo(ApplicationUser info, IEnumerable<UserRole> roles)
    {
        var ret= FromInfo(info);
        ret.Roles = roles.Select(e => new SimpleEntityString() {Id=e.Id, Text=e.Name}).ToList();
        return ret;
    }

这也演示了使用任何角色信息的 where 子句(上面只选择了我们的 Admin 和 Employee 角色中的用户)。

注意:这个内部加入了 IdentityUserRole,所以只有具有角色的用户才会被返回,如果你想要所有用户只需在 join roleIds... 行的末尾添加一个“into identRoles”并相应地修改其余条件。

您可以使用 EF Core 5.0 多对多功能,并避免继承 IdentityUserRole/IdentityRole。

应用用户

using System.Collections.Generic;
using Microsoft.AspNetCore.Identity;

public class ApplicationUser : IdentityUser
{
    public ICollection<IdentityRole> Roles { get; set; }
}

数据库上下文:

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    ...

    protected override void OnModelCreating(ModelBuilder builder)
    {
            base.OnModelCreating(builder);

            builder.Entity<ApplicationUser>()
                .HasMany(u => u.Roles)
                .WithMany("Users")
                .UsingEntity<IdentityUserRole<string>>(
                    userRole => userRole.HasOne<IdentityRole>()
                        .WithMany()
                        .HasForeignKey(ur => ur.RoleId)
                        .IsRequired(),
                    userRole => userRole.HasOne<ApplicationUser>()
                        .WithMany()
                        .HasForeignKey(ur => ur.UserId)
                        .IsRequired());
    }
}

更新:

将 NuGet Duende.IdentityServer.EntityFramework.Storage升级到 6.1.0 时出现以下错误:

CS0535 'ApplicationApiAuthorizationDbContext<TUser, TRole>' 未实现接口成员 'IPersistedGrantDbContext.ServerSideSessions'

ApplicationApiAuthorizationDbContext.cs现在需要另一个DbSet ,如下所示:

    public DbSet<ServerSideSession> ServerSideSessions
    {
        get;
        set;
    }

尽管对于endpoints.MapRazorPages();这导致了下面的错误。 .

System.Reflection.ReflectionTypeLoadException: '无法加载一种或多种请求的类型。 来自程序集“Microsoft.AspNetCore.ApiAuthorization.IdentityServer, Version=6.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60”的“Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ApiAuthorizationDbContext`1”类型中的方法“get_ServerSideSessions”没有实现。 '

建议在解决此问题之前继续使用Duende.IdentityServer.EntityFramework.Storage 5.2.0

原来的:

正如@Dreamescaper 和@graycrow 所说,您可以在EF Core 5.0 中使用影子多对多导航,即使它不应该工作。

https://github.com/dotnet/efcore/issues/25383#issuecomment-894785144

https://github.com/dotnet/efcore/issues/23362

EF Core 7.0 中可能会再次通过影子导航添加单向多对多关系但尚未完成的支持:

https://github.com/dotnet/efcore/issues/3864

我使用 EF Core 6.0 让它像这样工作:

应用用户:

public class ApplicationUser : IdentityUser
{
    public ICollection<ApplicationRole> Roles { get; set; }
}

应用角色:

public class ApplicationRole : IdentityRole
{
    public ICollection<ApplicationUser> Users { get; set; }

}

Program.csStartup.cs

services.AddDefaultIdentity<ApplicationUser>(options =>
options.SignIn.RequireConfirmedAccount = false)
    .AddRoles<ApplicationRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

ApplicationApiAuthorizationDbContext:

//Based on Microsoft.AspNetCore.ApiAuthorization.IdentityServer.ApiAuthorizationDbContext, Version=6.0.2.0
//https://github.com/dotnet/aspnetcore/issues/14161#issuecomment-533468760
public class ApplicationApiAuthorizationDbContext<TUser, TRole> : IdentityDbContext<TUser, TRole, string>, IPersistedGrantDbContext, IDisposable where TUser : IdentityUser where TRole : IdentityRole
{
    private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;

    public DbSet<PersistedGrant> PersistedGrants
    {
        get;
        set;
    }

    public DbSet<DeviceFlowCodes> DeviceFlowCodes
    {
        get;
        set;
    }

    public DbSet<Key> Keys
    {
        get;
        set;
    }

    public ApplicationApiAuthorizationDbContext(DbContextOptions options, IOptions<OperationalStoreOptions> operationalStoreOptions)
        : base(options)
    {
        _operationalStoreOptions = operationalStoreOptions;
    }

    Task<int> IPersistedGrantDbContext.SaveChangesAsync()
    {
        return base.SaveChangesAsync();
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);
    }
}

ApplicationDbContext继承自ApplicationApiAuthorizationDbContext<ApplicationUser, ApplicationRole>而不是ApiAuthorizationDbContext<ApplicationUser>

public class ApplicationDbContext : ApplicationApiAuthorizationDbContext<ApplicationUser, ApplicationRole>

modelBuilder.Entity<ApplicationUser>()
    .HasMany(u => u.Roles)
    .WithMany(r => r.Users)
    .UsingEntity<IdentityUserRole<string>>(
        userRole => userRole.HasOne<ApplicationRole>()
            .WithMany()
            .HasForeignKey(ur => ur.RoleId)
            .IsRequired(),
        userRole => userRole.HasOne<ApplicationUser>()
            .WithMany()
            .HasForeignKey(ur => ur.UserId)
            .IsRequired());

然后,您可以获得具有以下角色的所有用户:

var usersWithRoles = dbContext.Users.Include(x => x.Roles).ToList();

在此处输入图像描述

我为这个问题实施了一个解决方案,在性能和复杂性之间取得了我满意的平衡。 我们执行少量数据库往返,每个角色一次,而不是每个用户一次。 不需要 DbMigrations 或类覆盖。

        //Fetch all the Users
        var users = await userManager.Users
            .Select(u => new { User = u, Roles = new List<string>() })
            .ToListAsync();

        //Fetch all the Roles
        var roleNames = await roleManager.Roles.Select(r => r.Name).ToListAsync();

        foreach (var roleName in roleNames)
        {
            //For each role, fetch the users
            var usersInRole = await userManager.GetUsersInRoleAsync(roleName);

            //Populate the roles for each user in memory
            var toUpdate = users.Where(u => usersInRole.Any(ur => ur.Id == u.User.Id));
            foreach (var user in toUpdate)
            {
                user.Roles.Add(roleName);
            }
        }

接受的答案需要通过扩展自定义身份,否则将禁用角色管理器和用户管理器。 自定义 ASP.NET Core Identity 时,不应再使用 AddEntityFrameworkStores。 因为它将覆盖您以前的所有设置和自定义到默认身份服务。 首先,您需要创建具有以下签名的新服务: 为什么这违反了类型参数“TUser”的约束?

无需扩展,使用 userManager 和 roleManager:

namespace identityDemo.Controllers
{
    public class UserManagementController : Controller
    {
        private readonly ApplicationDbContext _context;
        private readonly RoleManager<IdentityRole> _roleManager;
        private readonly UserManager<IdentityUser> _userManager;

            public UserManagementController(ApplicationDbContext context, 
UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager)
        {
            _context = context;
            _roleManager = roleManager; 
            _userManager = userManager; 
        }

        // GET: ApplicationUserRoles
        public async Task<IActionResult> GetApplicationUsersAndRoles()
        {
            return View(new UserMv(
                (from user in await _userManager.Users.ToListAsync()
                 select new UserMv(user, GetUserRoles(user).Result)).ToList()));
        }

        private async Task<List<string>> GetUserRoles(IdentityUser user)
        {
            return new List<string>(await _userManager.GetRolesAsync(user));
        }
}

使用简单的构造函数映射到 DTO:

namespace IdentityDemo.Models.ModelView
{
    public class UserMv
    {
public UserMv(IdentityUser aus, List<string> userRoles)
        {
            UserId = aus.Id;
            UserName = aus.UserName;
            RolesHeld = userRoles; 
            Email = aus.Email;
            EmailConfirmed = aus.EmailConfirmed;
            LockoutEnabled = aus.LockoutEnabled;
            AccessFailedCount = aus.AccessFailedCount;
        }
}

和启动.cs

services.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();

ASP.NET 核心 3.1 更新

我使用以下代码,它完美地工作

  namespace MyProject.Pages.Roles
{
    public class DetailsModel : PageModel
    {

        public UserManager<ApplicationUser> _userManager;
        public RoleManager<IdentityRole> _roleManager;
        private readonly ApplicationDbContext _context;

        public DetailsModel(UserManager<ApplicationUser> userManager,
            RoleManager<IdentityRole> roleManager,
            ApplicationDbContext context)
        {
            _userManager = userManager;
            _roleManager = roleManager;
            _context = context;
        }

        public IList<IdentityRole> Roles { get; set; }

        [BindProperty]
        public IList<ApplicationUser> applicationUserList { get; set; }

        [BindProperty]
        public IList<IdentityRole> allRolesList { get; set; }

        public IList<IdentityUserRole<string>> usersRoles { get; set; }
        public IList<IdentityUserRole<string>> usersRole { get; set; }
        public IList<IdentityUserRole<string>> userWithRole { get; set; }


        public Dictionary<ApplicationUser, string> itemDictionary;

        public async Task<IActionResult> OnGetAsync(string id)
        {
            if (id == null)
            {
                return NotFound();
            }


            Roles = await _context.Roles.Where(r => r.Id == id).ToListAsync();

            allRolesList = await _context.Roles.ToListAsync();

            usersRoles = await _context.UserRoles.ToListAsync();
            usersRole = await _context.UserRoles.Where(r => r.RoleId == id).ToListAsync();
            userWithRole = usersRoles.Where(u => u.RoleId == id).ToList();

            applicationUserList = await _context.Users.ToListAsync();

            itemDictionary = new Dictionary<ApplicationUser, string> { };

            foreach (var item in usersRole)
            {
                itemDictionary.Add(await _context.Users.FindAsync(id = item.UserId), item.UserId);
            }

            return Page();
        }
    }
}

绑定所有这些东西以了解发生了什么非常有用!

在详细信息 Razor 页面上,我只有

    @page "{id}"
@model MyProject.Pages.Roles.DetailsModel
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    var dict = Model.itemDictionary;
    int cou = dict.Count();
    var x = Model.applicationUserList;
}

<h5 class="bg-primary text-white text-center p-2">List of Members having the role @Model.Roles[0].Name</h5>
<table class="table">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => model.userWithRole[0].UserId)</th>
            <th>@Html.DisplayNameFor(model => model.userWithRole[0].RoleId)</th>
            <th>LastName, FirstName</th>
        </tr>
    </thead>

    <tbody>

        @foreach (var kvp in dict.ToArray())
        {
            <tr>
                <td>@kvp.Key</td>
                <td>@kvp.Value</td>
                <td>@kvp.Key.LastName, @kvp.Key.FirstName</td>
            </tr>
        }

    </tbody>
</table>

结果如下:

在此处输入图片说明

完美地工作。 我使用的是整数键,所以我用“int”替换了“string”

ApplicationRole : IdentityRole<int>
ApplicationUserRole : IdentityUserRole<int>
ApplicationUser : IdentityUser<int>

ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, 
IdentityUserClaim<int>,
ApplicationUserRole, IdentityUserLogin<int>, IdentityRoleClaim<int>, 
IdentityUserToken<int>>

Linq: RoleId = (from a in m.UserRoles select a.Role.Id).FirstOrDefault(),

有一篇关于微软文档的有用文章https://docs.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-5.0

对我来说,暴露导航属性(角色、用户)看起来像这样(NET 5):

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
    public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; }
    public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; }
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

public class ApplicationRole : IdentityRole
{
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

public class ApplicationUserRole : IdentityUserRole<string>
{
    public virtual ApplicationUser User { get; set; }
    public virtual ApplicationRole Role { get; set; }
}

public class ApplicationDbContext
: IdentityDbContext<
    ApplicationUser, ApplicationRole, string,
    IdentityUserClaim<string>, ApplicationUserRole, IdentityUserLogin<string>,
    IdentityRoleClaim<string>, IdentityUserToken<string>>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>(b =>
        {
            // Each User can have many UserClaims
            b.HasMany(e => e.Claims)
                .WithOne()
                .HasForeignKey(uc => uc.UserId)
                .IsRequired();

            // Each User can have many UserLogins
            b.HasMany(e => e.Logins)
                .WithOne()
                .HasForeignKey(ul => ul.UserId)
                .IsRequired();

            // Each User can have many UserTokens
            b.HasMany(e => e.Tokens)
                .WithOne()
                .HasForeignKey(ut => ut.UserId)
                .IsRequired();

            // Each User can have many entries in the UserRole join table
            b.HasMany(e => e.UserRoles)
                .WithOne(e => e.User)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();
        });

        modelBuilder.Entity<ApplicationRole>(b =>
        {
            // Each Role can have many entries in the UserRole join table
            b.HasMany(e => e.UserRoles)
                .WithOne(e => e.Role)
                .HasForeignKey(ur => ur.RoleId)
                .IsRequired();
        });

    }
}

请注意,在 ApplicationDbContext 中,您可以更改主键类型(在我的情况下为字符串)

您可以使用 sql 命令(如底部代码)来获取所有管理员用户(无需将任何 class 导入您的模型):

            var adminUsers = await _db.Users
.FromSqlRaw("select AspNetUsers.* from AspNetUsers with(nolock)"+
" join AspNetUserRoles with(nolock) on UserId = AspNetUsers.id"+
" join AspNetRoles with(nolock) on AspNetRoles.id = AspNetUserRoles.RoleId"+
" where AspNetRoles.name = 'Admin'").ToListAsync();

在上面的代码中 _db 是您的数据库上下文。

我需要在视图中显示用户拥有的所有角色,而不是这里已经提供的解决方案,我采用了这个快速而肮脏的方法:

@foreach(var user in Model.Users)
        {
        <tr>
            <td>@user.Email</td>
            <td>@String.Join(", ", @Model._userManager.GetRolesAsync(user).GetAwaiter().GetResult().ToArray())</td>
        </tr>
        }

_userManager 必须是公开的才能工作。 而 user 只是 IdentityUser 的一个实例。

我通过创建一个包含我需要的所有列(包括角色)的视图并将其添加到上下文中来解决这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM