In EF Core 2.0 Identity navigation properties are not included by default, so after upgrading, I added them. So for Many-To-Many relationship between User and Role, and One
I do not know why, there are not these useful navigation properties. I want to list users with their roles.
So I did the follow:
public class ApplicationUser : IdentityUser
{
public virtual ICollection UserRoles { get; } = new List();
}
public class ApplicationUserRole : IdentityUserRole
{
public virtual ApplicationUser User { get; set; }
public virtual ApplicationRole Role { get; set; }
}
public class ApplicationRole : IdentityRole
{
public ApplicationRole(){ }
public ApplicationRole(string roleName)
: base(roleName)
{
}
public virtual ICollection UserRoles { get; } = new List();
}
This creates the navigation, but it creates additional columns like RoleId1
and Discriminator
. So, I added the following according to Add IdentityUser POCO Navigation Properties.
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity()
.HasMany(e => e.UserRoles)
.WithOne()
.HasForeignKey(e => e.UserId)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
builder.Entity()
.HasOne(e => e.User)
.WithMany(e => e.UserRoles)
.HasForeignKey(e => e.UserId);
builder.Entity()
.HasOne(e => e.Role)
.WithMany(e => e.UserRoles)
.HasForeignKey(e => e.RoleId);
}
But I still have both columns RoleId1
and Discriminator
. After that, I replace with the new ApplicationRole class in ApplicationDbContext, DI configuration service and DB seed.
public class ApplicationDbContext : IdentityDbContext
, ApplicationUserRole, IdentityUserLogin, IdentityRoleClaim, IdentityUserToken>
{
...
}
public void ConfigureServices(IServiceCollection services)
{
...
services.AddIdentity()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
...
}
public DbInitializer(
ApplicationDbContext context,
UserManager userManager,
RoleManager 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));
}
Also, I could navigate and get the first name of role.
ctx.Users.Select(e => new
{
e.Id,
e.UserName,
e.Email,
e.PhoneNumber,
Roles = e.UserRoles.Select(i => i.Role.Name).ToList()
}).ToList();
I hope this give you a clue for Claims
navigation property.