我有多个类( A
、 B
和 C
)每个扩展 IdentityUser<Guid>
.我还有一个名为 UserRole
的类(class)延伸 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> { }
以下是我遇到的错误:
Specified argument was out of the range of valid values. (Parameter 'instance 'AUserStore' with ReturnType AUserStore cannot be cast to 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>();
最佳答案
关于 AddIdentity
和 AddIdentityCore
的评论都有这个:
Adds and configures the identity system for the specified User and Role types.
和,
- 比较 AddIdentity<> 的源代码和 AddIdentityCore<> ,
查看项目模板中的默认代码:
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 注册多种身份类型时,它会感到困惑,但我们确实需要它。
我相信您正在寻找的是这些帖子:
- Inheritance with EF Code First: Part 1 – Table per Hierarchy (TPH)
- Inheritance with EF Code First: Part 2 – Table per Type (TPT)
- Inheritance with EF Code First: Part 3 – Table per Concrete Type (TPC)
您有 3 个以上的 normal
选项来映射
您的任何 UserType
数据到数据库。第一个选项为您提供最佳性能,但当您的用户类型非常复杂时,它会给您带来非常困惑的 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>
{
}
好好享受吧。
关于.net-core - .NET Core 标识多种用户类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58848481/