EF Core 2如何在IdentityUser上包含角色导航属性?

lee*_*n3o 9 asp.net-identity entity-framework-core asp.net-core

我正在使用EF Core 2设置一个新项目,我需要在IdentityUser上有一个导航属性,所以当我查询用户时,我可以包含(x => x.Roles)并获取用户所在的角色.

这篇关于Github的帖子有一些想法,但是我通过在Identity表上创建新的/重复的字段或导致迁移问题,尝试了每个问题和所有问题.EF团队的任何人都没有官方评论.

https://github.com/aspnet/Identity/issues/1361

我想知道是否有人这样正常工作?并且可以共享他们的EF DB映射和模型.

Cal*_*alC 15

请参阅"将身份验证和身份迁移到ASP.NET Core 2.0"文档,特别是" 添加IdentityUser POCO导航属性 "部分:

IdentityUser已删除基本POCO(Plain Old CLR Object)的Entity Framework(EF)Cor​​e导航属性 .如果您的1.x项目使用了这些属性,请手动将它们添加回2.0项目:

/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
public virtual ICollection<IdentityUserRole<int>> Roles { get; } = new List<IdentityUserRole<int>>();
Run Code Online (Sandbox Code Playgroud)

要在运行EF Core Migrations时防止重复的外键,请将以下内容添加到IdentityDbContext类的OnModelCreating 方法中(在base.OnModelCreating();调用之后):

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    // Customize the ASP.NET Identity model and override the defaults if needed.
    // For example, you can rename the ASP.NET Identity table names and more.
    // Add your customizations after calling base.OnModelCreating(builder);

    builder.Entity<ApplicationUser>()
        .HasMany(e => e.Roles)
        .WithOne()
        .HasForeignKey(e => e.UserId)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);
}
Run Code Online (Sandbox Code Playgroud)

编辑

以上内容仅满足通过IdentityUserRole链接表访问用户对角色持有的角色的任务.要通过导航属性访问角色实体本身,您需要添加另一个导航属性(这次是针对从中继承的实体IdentityUserRole).请参阅以下步骤:

  1. 修改实体的Roles导航属性IdentityUser,如下所示:
public virtual ICollection<UserRole> Roles { get; set; } = new List<UserRole>();
Run Code Online (Sandbox Code Playgroud)
  1. 创建UserRole上面引用的实体:
public class UserRole : IdentityUserRole<int>
{
    public virtual IdentityRole<int> Role { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
  1. 构造映射UserRole如下:
builder.Entity<UserRole>()
    .HasOne(e => e.Role)
    .WithMany()
    .HasForeignKey(e => e.RoleId)
    .IsRequired()
    .OnDelete(DeleteBehavior.Cascade);
Run Code Online (Sandbox Code Playgroud)
  1. 然后,您可以检索实体(填充导航属性),如下所示:
User user = context.Set<User>()
    .Include(u => u.Roles)
    .ThenInclude(r => r.Role)
    .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

注意:

  • 由于这是加载多对多关系的另一方面,这可能导致对数据库的多次调用(请参阅N + 1问题).
  • 在创建从IdentityUserRole您继承的新实体时,您需要迁移或重新创建数据库.
  • 如果你想用这个导航属性与UserManagerRoleManager你需要使用的长篇超载 AddUserStore()AddRoleStore您的启动类,如
services.AddIdentity<User, IdentityRole<int>>()
    .AddUserStore<UserStore<User, IdentityRole<int>, SqlContext, int, IdentityUserClaim<int>, UserRole, IdentityUserLogin<int>, IdentityUserToken<int>, IdentityRoleClaim<int>>>()
    .AddRoleStore<RoleStore<IdentityRole<int>, SqlContext, int, UserRole, IdentityRoleClaim<int>>>()
    .AddDefaultTokenProviders();
Run Code Online (Sandbox Code Playgroud)

  • 杰出的。我希望我能给这个更多的赞成票。谢谢。 (2认同)

Moh*_*our 6

我通过自定义查询获取角色,可能会有所帮助。

var roles = (from role in _dbContext.Roles
    let userRoles = _dbContext.UserRoles.Where(ur => ur.UserId == user.Id).Select(ur => ur.RoleId)
    where userRoles.Contains(role.Id)
    select role
).ToList();
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

4822 次

最近记录:

8 年,5 月 前