EF Core 2 How do I enable the role navigation property on IdentityUser?

I am creating a new project using EF Core 2, and I need to have a navigation property on IdentityUser, so when I ask for a user, I can turn on (x => x.Roles) and get the user Roles located in.

There are some ideas in this post on Github, but I tried each of them and all the problems that came up, creating new / duplicate fields in Identity tables or causing migration issues. And no official comments from anyone on the EF team.

https://github.com/aspnet/Identity/issues/1361

I was wondering if this works correctly? And could share their EF DB mappings and models.

+5
source share
2 answers

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:

 /// <summary> /// Navigation property for the roles this user belongs to. /// </summary> public virtual ICollection<IdentityUserRole<int>> Roles { get; } = new List<IdentityUserRole<int>>(); 

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); // 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); } 

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>(); 
  1. Create the UserRole object specified above:
 public class UserRole : IdentityUserRole<int> { public virtual IdentityRole<int> Role { get; set; } } 
  1. Build the mapping for UserRole as follows:
 builder.Entity<UserRole>() .HasOne(e => e.Role) .WithMany() .HasForeignKey(e => e.RoleId) .IsRequired() .OnDelete(DeleteBehavior.Cascade); 
  1. 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(); 
+7
source

I get roles on custom request and may be useful.

 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
source

Source: https://habr.com/ru/post/1273990/


All Articles