See the documentation for โMigrating Authentication and Authentication to ASP.NET Core 2.0,โ in particular the section โ Add PICO Authentication Properties for IdentityUser Users โ
Entity Structure (EF) The basic navigation properties of the IdentityUser POCO base (Regular CLR object) have been removed. If your Project 1.x used these properties, manually adding them back to project 2.0:
To prevent duplication of foreign keys when starting EF Core Migrations, add the following to your IdentityDbContext class' OnModelCreating method (after calling base.OnModelCreating(); ):
protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder);
Edit
The task described above will only satisfy access tasks for role identifiers that were associated with the user through the IdentityUserRole reference table. To access the role object itself through the navigation property, you will need to add another navigation property (this time against an object inheriting from IdentityUserRole ). See the following steps:
- Change the
Roles navigation property on your IdentityUser object as follows:
public virtual ICollection<UserRole> Roles { get; set; } = new List<UserRole>();
- Create the
UserRole object specified above:
public class UserRole : IdentityUserRole<int> { public virtual IdentityRole<int> Role { get; set; } }
- Build the mapping for
UserRole as follows:
builder.Entity<UserRole>() .HasOne(e => e.Role) .WithMany() .HasForeignKey(e => e.RoleId) .IsRequired() .OnDelete(DeleteBehavior.Cascade);
- Then you can get the objects (with the filled navigation property) as follows:
User user = context.Set<User>() .Include(u => u.Roles) .ThenInclude(r => r.Role) .FirstOrDefault();
Note:
- Since this loads the other side of the many-to-many relationship, this can lead to more than one database call (see N + 1 problem ).
- When you create a new object that inherits from
IdentityUserRole , you will need to migrate or recreate the database. - If you want to use this navigation property using
UserManager or RoleManager you will need to use the long form of overloading AddUserStore() and AddRoleStore in your launch class, for example
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();