[英]EF Core 2.0 Identity - Adding navigation properties
在 EF Core 2.0 中,默认情况下不包含身份导航属性,因此在升级后,我添加了它们。 因此,对于 User 和 Role 之间的多对多关系,以及 Role 和 RoleClaim 之间的一对多关系,我添加了以下导航属性:
public class User : IdentityUser
{
[Required]
public string Name { get; set; }
public virtual ICollection<IdentityUserRole<string>> Roles { get; set; }
}
public class Role : IdentityRole
{
[Required]
public string Name { get; set; }
public virtual ICollection<IdentityRoleClaim<string>> Claims { get; set;}
}
令人惊讶的是增加了一个额外RoleId1
关键AspNetRoleClaims
表和UserId1
到AspNetUserRoles
表和所有实际使用新的密钥,而不是GET查询RoleId
和UserId
同样存在。
不知道为什么,没有这些有用的导航属性。 我想列出用户及其角色。
所以我做了以下事情:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<ApplicationUserRole> UserRoles { get; } = new List<ApplicationUserRole>();
}
public class ApplicationUserRole : IdentityUserRole<string>
{
public virtual ApplicationUser User { get; set; }
public virtual ApplicationRole Role { get; set; }
}
public class ApplicationRole : IdentityRole<string>
{
public ApplicationRole(){ }
public ApplicationRole(string roleName)
: base(roleName)
{
}
public virtual ICollection<ApplicationUserRole> UserRoles { get; } = new List<ApplicationUserRole>();
}
这会创建导航,但会创建其他列,如RoleId1
和Discriminator
。 所以,我根据Add IdentityUser POCO Navigation Properties添加了以下内容。
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>()
.HasMany(e => e.UserRoles)
.WithOne()
.HasForeignKey(e => e.UserId)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
builder.Entity<ApplicationUserRole>()
.HasOne(e => e.User)
.WithMany(e => e.UserRoles)
.HasForeignKey(e => e.UserId);
builder.Entity<ApplicationUserRole>()
.HasOne(e => e.Role)
.WithMany(e => e.UserRoles)
.HasForeignKey(e => e.RoleId);
}
但我仍然有两列RoleId1
和Discriminator
。 之后,我用 ApplicationDbContext、DI 配置服务和 DB 种子中的新 ApplicationRole 类替换。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserClaim<string>
, ApplicationUserRole, IdentityUserLogin<string>, IdentityRoleClaim<string>, IdentityUserToken<string>>
{
...
}
public void ConfigureServices(IServiceCollection services)
{
...
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
...
}
public DbInitializer(
ApplicationDbContext context,
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager)
{
_context = context;
_userManager = userManager;
_roleManager = roleManager;
}
public async void Initialize()
{
_context.Database.EnsureCreated();
if (!_context.Roles.Any(r => r.Name == SharedConstants.Role.ADMINISTRATOR))
await _roleManager.CreateAsync(new ApplicationRole(SharedConstants.Role.ADMINISTRATOR));
}
此外,我可以导航并获取角色的名字。
ctx.Users.Select(e => new
{
e.Id,
e.UserName,
e.Email,
e.PhoneNumber,
Roles = e.UserRoles.Select(i => i.Role.Name).ToList()
}).ToList();
我希望这能给你一个关于Claims
导航属性的线索。
我遇到同样的问题,在我的情况的问题造成的,因为我已经把电话给base.OnModelCreating(builder)
在底部OnModelCreating
。 在最顶部移动base.OnModelCreating(builder)
解决了这个问题(没有重复的列和 FK)。
感谢这个GitHub 问题
我遇到了同样的问题,这是解决方案。
您必须告诉 Ef 您将拥有 OneToMany Relation 的导航属性。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
CreateUserModel(modelBuilder.Entity<User>());
CreateRoleModel(modelBuilder.Entity<Role>());
}
private void CreateRoleModel(EntityTypeBuilder<Role> entityTypeBuilder)
{
entityTypeBuilder.HasMany(role => role.UserRoles).
WithOne(**e=> e.Role**).
HasForeignKey(userRole => userRole.RoleId).
IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
private void CreateUserModel(EntityTypeBuilder<User> entityTypeBuilder)
{
entityTypeBuilder.HasMany(user => user.UserRoles).
WithOne(**e=>e.User**).
HasForeignKey(userRole => userRole.UserId).
IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
您还可以在字符串中指定导航属性,例如
private void CreateRoleModel(EntityTypeBuilder<Role> entityTypeBuilder)
{
entityTypeBuilder.HasMany(role => role.UserRoles).
WithOne(**"Role"**).
HasForeignKey(userRole => userRole.RoleId).
IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
private void CreateUserModel(EntityTypeBuilder<User> entityTypeBuilder)
{
entityTypeBuilder.HasMany(user => user.UserRoles).
WithOne(**"User"**).
HasForeignKey(userRole => userRole.UserId).
IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.