EF Core 2如何在IdentityUser上包括角色导航属性? [英] EF Core 2 How To Include Roles Navigation Property On IdentityUser?
问题描述
我正在使用EF Core 2设置新项目,并且需要在IdentityUser上具有导航属性,因此当我查询用户时,我可以包含(x => x.Roles)并获取该用户的角色在里面.
I am setting up a new project using EF Core 2, and I need to have a navigation property on the IdentityUser so when I query for a user I can include(x => x.Roles) and get the Roles the user is in.
关于Github的这篇文章有一些想法,但是我通过在Identity表上创建新的/重复的字段来尝试每一个导致问题的原因,或者导致迁移的问题. EF团队中没有任何人发表官方评论.
This post on Github has some ideas, but I have tried each one and all cause issues, by creating new/duplicate fields on the Identity tables or cause issues with migrations. And no official comment from anyone in the EF team.
https://github.com/aspnet/Identity/issues/1361
我想知道是否有人能正常工作?并且可以共享他们的EF DB映射和模型.
I was wondering if anyone has this working correctly? And could share their EF DB mappings and models.
推荐答案
请参阅将身份验证和身份迁移到ASP.NET Core 2.0"文档,特别是"
See the documentation for 'Migrating Authentication and Identity to ASP.NET Core 2.0', specifically the section 'Add IdentityUser POCO Navigation Properties':
基础的Entity Framework(EF)核心导航属性
IdentityUser
POCO(普通旧CLR对象)已被删除.如果你的 1.x项目使用了这些属性,然后将它们手动添加回2.0项目:
The Entity Framework (EF) Core navigation properties of the base
IdentityUser
POCO (Plain Old CLR Object) have been removed. If your 1.x project used these properties, manually add them back to the 2.0 project:
/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
public virtual ICollection<IdentityUserRole<int>> Roles { get; } = new List<IdentityUserRole<int>>();
为防止在运行EF Core Migrations时出现重复的外键,请添加
IdentityDbContext
类的以下内容OnModelCreating
方法(在base.OnModelCreating();
调用之后):
To prevent duplicate foreign keys when running EF Core Migrations, add the following to your
IdentityDbContext
class'OnModelCreating
method (after thebase.OnModelCreating();
call):
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);
}
编辑
以上内容仅满足通过IdentityUserRole
链接表访问针对用户持有的角色ID的任务.要通过导航属性访问角色实体本身,您需要添加另一个导航属性(这次是针对从IdentityUserRole
继承的实体).请参阅以下步骤:
Edit
The above will only satisfy the task of accessing the role Ids held against a user via the IdentityUserRole
link table. To access the role entity itself via a navigation property, you would need to add another navigation property (this time against an entity inheriting from IdentityUserRole
). See the steps below:
- 按如下所示修改
IdentityUser
实体上的Roles
导航属性:
- Modify the
Roles
navigation property on yourIdentityUser
entity as follows:
public virtual ICollection<UserRole> Roles { get; set; } = new List<UserRole>();
- 创建上面引用的
UserRole
实体:
public class UserRole : IdentityUserRole<int>
{
public virtual IdentityRole<int> Role { get; set; }
}
- 按如下方式构造
UserRole
的映射:
- Construct the mapping for
UserRole
as follows:
builder.Entity<UserRole>()
.HasOne(e => e.Role)
.WithMany()
.HasForeignKey(e => e.RoleId)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
- 然后,您可以按以下方式检索实体(已填充导航属性):
User user = context.Set<User>()
.Include(u => u.Roles)
.ThenInclude(r => r.Role)
.FirstOrDefault();
注意:
- As this is loading another side of a many-to-many relatiohship, this may result in more than one call to the database (see N+1 problem).
- As you are creating a new entity that inherits from
IdentityUserRole
you will need to migrate or re-create the database. - If you want to use this navigation property with
UserManager
orRoleManager
you will need to use the long-form overload ofAddUserStore()
andAddRoleStore
in your startup class, e.g.
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();
这篇关于EF Core 2如何在IdentityUser上包括角色导航属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!