EF Core 2.0 Identity - 添加导航属性
Posted
技术标签:
【中文标题】EF Core 2.0 Identity - 添加导航属性【英文标题】:EF Core 2.0 Identity - Adding navigation properties 【发布时间】:2017-08-24 13:55:21 【问题描述】:在 EF Core 2.0 中,Identity 导航属性默认是不包含的,所以升级后我添加了。所以对于 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;
令人惊讶的是,它向AspNetRoleClaims
表和UserId1
向AspNetUserRoles
表添加了一个额外的RoleId1
键,并且所有get 查询实际上都使用新键而不是RoleId
和UserId
,它们也存在。
【问题讨论】:
在这个线程上查看答案***.com/a/47772406/82197 【参考方案1】:我不知道为什么,没有这些有用的导航属性。我想列出用户及其角色。
所以我做了以下操作:
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 中的新 ApplicationRole 类替换,DI 配置服务和 DB 种子。
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
导航属性的线索。
【讨论】:
感谢您非常彻底的回答。我刚刚遇到了这个问题,听从了您的建议,现在可以开始了!【参考方案2】:我遇到了同样的问题,在我的情况下,问题是因为我在OnModelCreating
的底部调用了base.OnModelCreating(builder)
。将base.OnModelCreating(builder)
移到最顶部解决了这个问题(没有重复的列和 FK)。
感谢GitHub issue
【讨论】:
【参考方案3】:我遇到了同样的问题,这是解决方案。
你必须告诉 Ef 你将在哪个导航属性上拥有 OneToMany 关系。
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);
【讨论】:
以上是关于EF Core 2.0 Identity - 添加导航属性的主要内容,如果未能解决你的问题,请参考以下文章
EF Core 2.0中开启Transaction事务会对DbContext创建和关闭数据库连接的行为有所影响
将现有 Microsoft.AspNet.Identity DB (EF 6) 迁移到 Microsoft.AspNetCore.Identity (EF Core)
.Net Core 2.0 Web API 使用 Identity / JWT 并让用户管理器使用 DI