.NET Core 标识多种用户类型 [英] .NET Core identity multiple User types

查看:21
本文介绍了.NET Core 标识多种用户类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个类(ABC),每个类都扩展了 IdentityUser.我还有一个名为 UserRole 的类,它扩展了 IdentityRole.

I have multiple classes (A, B and C) each extends IdentityUser<Guid>. I also have a class called UserRole which extends 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 的实例"AUserStore 强制转换为IUserStore')

Specified argument was out of the range of valid values. (Parameter 'instance 'AUserStore' with ReturnType AUserStore cannot be cast to IUserStore')

我不知道我正在做的事情是否可行.感谢您提供任何帮助或提示.

I don't know if what I'm doing is possible or not. Thanks for any help or hint.

更新

我想我已经成功了:

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>();

推荐答案

AddIdentityAddIdentityCore 的两个评论都有这样的:

Both comments on AddIdentity and AddIdentityCore have this:

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

Adds and configures the identity system for the specified User and Role types.

和,

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

  1. Compare source code for AddIdentity<> and AddIdentityCore<>,
  2. Review the default code from project template:

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 注册多个身份类型时,它会感到困惑,但我们确实需要它.

I would say: IdentityFramework got confused when you register multiple identity types to it, but we do need it.

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

I believe what you are looking for are these posts:

  1. EF Code First 的继承:第 1 部分 - 每个层次结构的表 (TPH)
  2. EF Code First 的继承:第 2 部分 - 每个类型的表 (TPT)
  3. 继承 EF Code First:第 3 部分 - 每个具体类型 (TPC) 的表

您有 3 个以上 normal 选项可以将您的任何 UserType 数据map 到数据库.第一个选项为您提供最佳性能,但是当您的用户类型非常复杂时,它会给您带来非常混乱的 datatable.您可以为您的实际项目选择其中任何一个作为平衡.

you have 3 above normal options to map your any UserType data to database. and the 1st options give you best performance, but give you very messive datatable when your usertypes are pretty complex. you would choose either of them for your real project as a balance.

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

Here is sample code with 1st approach:

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.

The next thing you want to configure is UserManager, instead of 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>
{

}

享受吧.

这篇关于.NET Core 标识多种用户类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆