C# LINQ IdentityContext 多组加入

C# LINQ IdentityContext Multi Group Join

我有这个 LINQ:

var users = _ctx.Users
    .AsEnumerable() // or "InvalidOperationException: This may indicate either a bug or a limitation in EF Core"
    .GroupJoin(_ctx.UserClaims, u => u.Id, c => c.UserId, (user, claims) => new { user, claims })
    .GroupJoin(_ctx.UserRoles, uc => uc.user.Id, r => r.UserId, (uc, roles) => new { uc.user, uc.claims, roles })
    .ToList()
    .Select(ucr => new UserDto
        {
            Id = ucr.user.Id,
            UserName = ucr.user.UserName,
            FirstName = ucr.user.FirstName,
            LastName = ucr.user.LastName,
            LastLogin = ucr.user.LastLogin,
            LockoutEnd = ucr.user.LockoutEnd,
            LockoutEnabled = ucr.user.LockoutEnabled,
            Roles = ucr.roles.Select(x => x.RoleId).Distinct().ToList(), // Here i would like the Role Name from the Roles Table by the UserRoles
            Scopes = ucr.claims.Select(x => x.ToClaim()).Where(x => x.Type.Equals(Shared.Scopes.Key)).Select(x => x.Value).ToList(),
            Claims = ucr.claims.Select(x => x.ToClaim()).Where(x => !x.Type.Equals(Shared.Scopes.Key)).ToList(),
            Enabled = ucr.user.Enabled
    }
).ToList();

这工作得很好,但我想获取用户的实际角色,而不仅仅是从 UserRoles 中获取用户到角色的映射

我尝试添加一个额外的 GroupJoin: .GroupJoin(_ctx.Roles, ucr => ucr.roles.Id, r => r.Id, (ucr, r) => new { u, r }) 但是因为 roles 是一个列表,所以我得到一个错误:

'IEnumerable<IdentityUserRole>' does not contain a definition for 'Id' and no accessible extension method 'Id' accepting a first argument of type 'IEnumerable<IdentityUserRole>'

关于如何获得实际角色列表的任何想法?

我使用的是默认身份 类 而不是 ApplicationUser

    public class ApplicationUser : IdentityUser
    {
        /// <summary>
        /// First Name
        /// </summary>
        [Display(Name = "First Name")]
        public string FirstName { get; set; }

        /// <summary>
        /// Last Name
        /// </summary>
        [Display(Name = "Last Name")]
        public string LastName { get; set; }

        /// <summary>
        /// Profile Picture
        /// </summary>
        public byte[] ProfilePicture { get; set; }

        /// <summary>
        /// Enabled
        /// </summary>
        public bool Enabled { get; set; }

        /// <summary>
        /// Last Login
        /// </summary>
        [Display(Name = "Last Login")]
        [DataType(DataType.DateTime)]
        [DisplayFormat(ApplyFormatInEditMode = true, NullDisplayText = "N/A", DataFormatString = "{0:yyyy-MM-dd HH:mm}")]
        public DateTime? LastLogin { get; set; } = null;

        /// <summary>
        /// Display Name
        /// </summary>
        [NotMapped]
        public string DisplayName => $"{FirstName} {LastName}";
    }

和 UserDto

public class UserDto
    {
        public UserDto()
        {
            Id = Guid.NewGuid().ToString();
            ConcurrencyStamp = Guid.NewGuid().ToString();
        }

        public string Id { get; set; }

        public string UserName { get; set; }

        public string NormalizedUserName => UserName.ToUpper();

        public string Email => UserName;

        public string NormalizedEmail => Email.ToUpper();

        public bool EmailConfirmed { get; set; }

        public string PasswordHash { get; set; }

        public string SecurityStamp { get; set; }

        public string ConcurrencyStamp { get; set; }

        public string PhoneNumber { get; set; }

        public bool PhoneNumberConfirmed { get; set; }

        public bool TwoFactorEnabled { get; set; }

        public DateTimeOffset? LockoutEnd { get; set; }

        public bool LockoutEnabled { get; set; }

        public int AccessFailedCount { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public byte[] ProfilePicture { get; set; }

        public DateTime? LastLogin { get; set; }

        public bool Enabled { get; set; }

        public List<string> Roles { get; set; }

        public List<Claim> Claims { get; set; }

        public List<string> Scopes { get; set; }
    }

加入UserRolesRoles,所以使用群组加入。

     var users = _ctx.Users
        .AsEnumerable()
        .GroupJoin(_ctx.UserClaims, u => u.Id, c => c.UserId, (user, claims) => new { user, claims })
        .GroupJoin(
            _ctx.UserRoles.Join(_ctx.Roles, ur => ur.RoleId, r => r.Id, (userRole, role) => new { userRole, role }),
            uc => uc.user.Id, r => r.userRole.UserId,
            (uc, roles) => new { uc.user, uc.claims, roles})
        .Select(ucr => new
        {
            Id = ucr.user.Id,
            UserName = ucr.user.UserName,
            FirstName = ucr.user.FirstName,
            LastName = ucr.user.LastName,
            LastLogin = ucr.user.LastLogin,
            LockoutEnd = ucr.user.LockoutEnd,
            LockoutEnabled = ucr.user.LockoutEnabled,
            Roles = ucr.roles.Select(x => x.role.Name).Distinct().ToList(),
            Scopes = ucr.claims.Select(x => x.ToClaim()).Where(x => x.Type.Equals(Shared.Scopes.Key)).Select(x => x.Value).ToList(),
            Claims = ucr.claims.Select(x => x.ToClaim()).Where(x => !x.Type.Equals(Shared.Scopes.Key)).ToList(),
            Enabled = ucr.user.Enabled
        }
    ).ToList();