Multiple user type Identity - DbContext design

Nod*_*.JS 8 c# entity-framework asp.net-identity .net-core asp.net-core

I'm trying to use the Identity package of .NET Core with multiple classes that extend IdentityUser<Guid> but with a single UserRole class.

I have multiple classes that extend UserStore<T> for each user type and a single class that extends RoleStore<UserRole>.

The following is my startup.cs:

services.AddIdentity<InternalUser, UserRole>(IdentityOptions)
    .AddDefaultTokenProviders()
    .AddUserStore<InternalUserStore>()
    .AddRoleStore<GenericUserRoleStore>();

services.AddIdentityCore<Contractor>(IdentityOptions)
    .AddRoles<UserRole>()
    .AddDefaultTokenProviders()
    .AddUserStore<ContractorUserStore>()
    .AddRoleStore<GenericUserRoleStore>();

services.AddIdentityCore<Homeowner>(IdentityOptions)
    .AddRoles<UserRole>()
    .AddDefaultTokenProviders()
    .AddUserStore<HomeownerUserStore>()
    .AddRoleStore<GenericUserRoleStore>();
Run Code Online (Sandbox Code Playgroud)

My DbContext is not extending IdentityDbContext:

public sealed class EntityDbContext: DbContext { }
Run Code Online (Sandbox Code Playgroud)

I was getting multiple errors so I added the following to DbContext but I commented it out:

public DbSet<IdentityUserClaim<Guid>> UserClaims { get; set; }

public DbSet<IdentityUserRole<Guid>> UserRoles { get; set; }
Run Code Online (Sandbox Code Playgroud)

I'm getting many different errors:

build Error on Instance 'Dal.IdentityStores.InternalUserStore' for PluginType IUserStore - and Instance 'RoleManager' for PluginType Microsoft.AspNetCore.Identity.RoleManager1[Models.Entities.Users.UserRole] - and Instance 'Dal.IdentityStores.GenericUserRoleStore' for PluginType Microsoft.AspNetCore.Identity.IRoleStore1[Models.Entities.Users.UserRole] - and Instance 'Dal.IdentityStores.GenericUserRoleStore' for PluginType Microsoft.AspNetCore.Identity.IRoleStore1[Models.Entities.Users.UserRole] - and Instance 'Dal.IdentityStores.ContractorUserStore' for PluginType Microsoft.AspNetCore.Identity.IUserStore1[Models.Entities.Contractors.Contractor] - and Instance 'UserClaimsPrincipalFactory' for PluginType Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1[Models.Entities.Contractors.Contractor] - and Instance 'UserClaimsPrincipalFactory<Contractor, UserRole>' for PluginType Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1[Models.Entities.Contractors.Contractor] - and Instance 'UserManager' for PluginType Microsoft.AspNetCore.Identity.UserManager1[Models.Entities.Homeowners.Homeowner] - and Instance 'UserClaimsPrincipalFactory<Homeowner>' for PluginType Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory1[Models.Entities.Homeowners.Homeowner]

This is the link to my repo

Van*_*dze 5

我重现了您的问题,下面是它的解决方案,但我会再次考虑为不同的用户角色创建多个表。

以下是反对多个用户表的两个主要原因:

  1. 当您想通过 id 查找用户时(假设您不知道角色),您将需要对不同的表运行多个查询,这会降低性能并增加代码的复杂性。
  2. 它还可能会增加数据库的复杂性,因为您需要为其他表设置多个外键。

如果您仍然希望为不同的用户角色拥有多个表,这里有一个小“技巧”​​。您只需要重写OnModelCreating方法并配置实体:

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<Contractor>(b =>
        {
            b.HasMany<IdentityUserRole<Guid>>().WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
        });

        builder.Entity<UserRole>(b =>
        {
            b.HasKey(r => r.Id);
            b.HasIndex(r => r.NormalizedName).HasName("RoleNameIndex").IsUnique();
            b.ToTable("AspNetRoles");
            b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();

            b.Property(u => u.Name).HasMaxLength(256);
            b.Property(u => u.NormalizedName).HasMaxLength(256);

            b.HasMany<IdentityUserRole<Guid>>().WithOne().HasForeignKey(ur => ur.RoleId).IsRequired();
            b.HasMany<IdentityRoleClaim<Guid>>().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired();
        });

        builder.Entity<IdentityRoleClaim<Guid>>(b =>
        {
            b.HasKey(rc => rc.Id);
            b.ToTable("AspNetRoleClaims");
        });

        builder.Entity<IdentityUserRole<Guid>>(b =>
        {
            b.HasKey(r => new { r.UserId, r.RoleId });
            b.ToTable("AspNetUserRoles");
        });

        builder.Entity<UserRole>().ToTable("Roles");
        builder.Entity<IdentityUserRole<Guid>>().ToTable("UserRoles");
        builder.Entity<IdentityRoleClaim<Guid>>().ToTable("RoleClaims");
        builder.Entity<IdentityUserClaim<Guid>>().ToTable("UserClaims");
    }
Run Code Online (Sandbox Code Playgroud)

之后,您应该能够登录。