.NET Core身份多种用户类型

时间:2019-11-14 02:24:30

标签: .net-core asp.net-identity

我有多个类(ABC)分别扩展了IdentityUser<Guid>。我还有一个名为UserRole的类,它扩展了IdentityRole<Guid>

以下是我的DbContext

public sealed class EntityDbContext: DbContext
{
    public DbSet<A> As { get; set; }

    public DbSet<B> Bs { get; set; }

    public DbSet<C> Cs { get; set; }

}

我在IServiceCollection中添加了身份:

        services
            .AddIdentityCore<A>()
            .AddEntityFrameworkStores<EntityDbContext>()
            .AddRoles<UserRole>()
            .AddUserStore<AUserStore>()
            // .AddRoleStore<TRoleStore>()
            .AddDefaultTokenProviders();

        // Same for B, C

我还有以下商店:

public class AUserStore : UserStore<A, UserRole, EntityDbContext, Guid> { } 
public class BUserStore : UserStore<B, UserRole, EntityDbContext, Guid> { } 
public class CUserStore : UserStore<C, UserRole, EntityDbContext, Guid> { } 

以下是我遇到的错误:

  

指定的参数超出有效值范围。 (参数   具有ReturnType AUserStore的'instance'AUserStore'无法转换为   IUserStore')

我不知道我在做什么是否可行。感谢您的帮助或提示。


更新

我认为我可以使用它

class GenericUserRoleStore : RoleStore<UserRole, EntityDbContext, Guid> { }

        services.AddIdentity<A, UserRole>()
            .AddDefaultTokenProviders()
            .AddUserStore<AUserStore>()
            .AddRoleStore<GenericUserRoleStore>();

        services.AddIdentityCore<B>()
            .AddRoles<UserRole>()
            .AddDefaultTokenProviders()
            .AddUserStore<BUserStore>()
            .AddRoleStore<GenericUserRoleStore>();

        services.AddIdentityCore<C>()
            .AddRoles<UserRole>()
            .AddDefaultTokenProviders()
            .AddUserStore<CUserStore>()
            .AddRoleStore<GenericUserRoleStore>();

1 个答案:

答案 0 :(得分:1)

AddIdentityAddIdentityCore的评论都具有以下内容:

  

为指定的用户和角色类型添加和配置身份系统。

  1. 比较AddIdentity<>AddIdentityCore<>的源代码,
  2. 查看项目模板中的默认代码:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddIdentity<ApplicationUser, ApplicationRole>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();
        ....
    }
    

我会说:向您注册多个身份类型时,IdentityFramework感到困惑,但是我们确实需要它。

我相信您正在寻找的是这些帖子:

  1. Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)
  2. Inheritance with EF Code First: Part 2 – Table per Type (TPT)
  3. Inheritance with EF Code First: Part 3 – Table per Concrete Type (TPC)

您在normal上方有3个选项可以将map的任何数据UserType存入数据库。和1st选项可为您提供最佳性能,但是当您的用户类型非常复杂时,datatable却会给您带来混乱。您可以为您的实际项目选择其中一个作为余额。

这是第一种方法的示例代码:

public class ApplicationUser : IdentityUser<int>
{
    public ApplicationUser() : base()
    {
        UserRoles = new HashSet<ApplicationUserRole>();
    }

    public int YearsOfExperience { get; set; }

    [InverseProperty("User")]
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}


public class ProjectManager : ApplicationUser
{
    public bool Talktive { get; set; }
}

public class Developer : ApplicationUser
{
    public bool IsCSharper { get; set; }
}

public class Tester : Developer
{
    public bool WhiteBox { get; set; }
}

public class Documenter : Tester
{
    public List<string> Languages { get; set; } = new List<string>();
}


public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    //get following users directly by following properties
    public DbSet<ProjectManager>  ProjectManagers { get; set; }
    public DbSet<Developer>  Developers { get; set; }
    public DbSet<Tester>  Testers { get; set; }
    public DbSet<Documenter>  Documenters { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        //prevent creating tables for following usertypes
        builder.Ignore<ProjectManager>();
        builder.Ignore<Developer>();
        builder.Ignore<Tester>();
        builder.Ignore<Documenter>();


        base.OnModelCreating(builder);

        builder.Entity<ApplicationUser>(entity =>
        {
            entity.HasMany(u => u.UserRoles).WithOne(x => x.User).HasForeignKey(c => c.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);

            //tell database to use this column as Discriminator
            entity.HasDiscriminator<string>("UserType");
        });

        builder.Entity<ApplicationRole>(entity =>
        {
            entity.HasKey(x => x.Id);
        });

        builder.Entity<ApplicationUserRole>(entity =>
        {
            entity.HasKey(c => new { c.UserId, c.RoleId });
            entity.HasOne(x => x.Role).WithMany(x => x.UserRoles).HasForeignKey(x => x.RoleId).IsRequired().OnDelete(DeleteBehavior.Cascade);
            entity.HasOne(x => x.User).WithMany(x => x.UserRoles).HasForeignKey(x => x.UserId).IsRequired().OnDelete(DeleteBehavior.Cascade);
        });
    }
}

当您需要用户时:

var allUsers = await _dbContext.Users.ToListAsync();
var allProjectManagers = await _dbContext.ProjectManagers.ToListAsync();
var allDevelopers = await _dbContext.Developers.ToListAsync();
var allTesters = await _dbContext.Testers.ToListAsync();

接下来要配置的是UserManager,而不是IUserStore。

public class ApplicationUserManager<TUser, TRole>
    where TUser : ApplicationUser
    where TRole : ApplicationRole

{
    private readonly ApplicationDbContext _context;
    private readonly UserManager<TUser> _userManager;
    private readonly RoleManager<TRole> _roleManager;

    public ApplicationUserManager(ApplicationDbContext context,
        UserManager<TUser> userManager,
        RoleManager<TRole> roleManager)
    {
        _context = context;
        _userManager = userManager;
        _roleManager = roleManager;
    }
    //customize your own base logics here.

}

public class DeveloperUserManager : ApplicationUserManager<Developer, ApplicationRole>
{

}

public class DocumenterUserManager : ApplicationUserManager<Documenter, ApplicationRole>
{

}

享受吧。