簡體   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