我正在使用EF Core 2设置一个新项目,我需要在IdentityUser上有一个导航属性,所以当我查询用户时,我可以包含(x => x.Roles)并获取角色用户在。
这篇关于Github的帖子有一些想法,但我通过在Identity表上创建新的/重复的字段或导致迁移问题,尝试了每个问题和所有问题。 EF团队的任何人都没有官方评论。
https://github.com/aspnet/Identity/issues/1361
我想知道是否有人这样正常工作?并且可以共享他们的EF DB映射和模型。
答案 0 :(得分:14)
请参阅“将身份验证和身份迁移到ASP.NET Core 2.0'”的文档,特别是' Add IdentityUser POCO Navigation Properties':
基础的实体框架(EF)核心导航属性
IdentityUser
POCO(普通旧CLR对象)已被删除。如果你的 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>>();
要在运行EF Core Migrations时防止重复的外键,请添加 以下内容适用于
IdentityDbContext
课程&#39;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);
}
以上内容仅满足通过IdentityUserRole
链接表访问用户对角色所持有的角色的任务。要通过导航属性访问角色实体本身,您需要添加另一个导航属性(这次是针对从IdentityUserRole
继承的实体)。请参阅以下步骤:
Roles
实体上的IdentityUser
导航属性,如下所示:public virtual ICollection<UserRole> Roles { get; set; } = new List<UserRole>();
UserRole
实体:public class UserRole : IdentityUserRole<int>
{
public virtual IdentityRole<int> Role { get; set; }
}
UserRole
的映射,如下所示: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();
注意:
IdentityUserRole
的新实体时,您将需要迁移或重新创建数据库。UserManager
或使用
RoleManager
你将需要使用长形式的重载
启动类中的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();
答案 1 :(得分:3)
我通过自定义查询获取角色,可能会有所帮助。
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();
答案 2 :(得分:1)
将我的10美分加进本已辉煌的accepted answer。重要的是要记住使DbContext
适应您将要进行的更改。
在接受答案的情况下,您DbContext
的外观应与此类似:
public class DbContext: IdentityDbContext<User, IdentityRole<int>, string,
IdentityUserClaim<string>, UserRole, IdentityUserLogin<string>,
IdentityRoleClaim<string>, IdentityUserToken<string>>,
IDesignTimeDbContextFactory<ApplicationContext>
{
// ...Rest of the code goes here
}
请注意,UserRole
将替换默认的TUserRole
参数。花了我几个小时来解决这个问题,希望它可以节省一些时间。