EF Core 2.0 Identity - Adding navigation properties

后端 未结 3 1234
面向向阳花
面向向阳花 2021-01-02 21:58

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

3条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-02 22:37

    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.

提交回复
热议问题