如何使用 IdentityUser 创建两个差异 table

How create two difference table with IdentityUser

核心 2.2 中的项目

我有两个 类 继承了 IdentityUser 其中第一个

 public class DeveloperModel : IdentityUser
{
    [Required(AllowEmptyStrings = false)]
    public string FirstName { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string SecondName { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string Company { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string CompanyName { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string CompanyAdress { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string CompanyEmail { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string CompanyPhoneNumber { get; set; }
}

和第二个

public class UserModel : IdentityUser
{
    [Required(AllowEmptyStrings = false)]
    public string FirstName { get; set; }

    [Required(AllowEmptyStrings = false)]
    public string SecondName { get; set; }

}

我对这两个的背景 类

 public class EFDbContext : IdentityDbContext
{
    public EFDbContext(DbContextOptions<EFDbContext> options) : base(options)
    {

    }

    public DbSet<UserModel> UserModels { get; set; }
    public DbSet<DeveloperModel> DeveloperModels { get; set; }
}

对于迁移的结束,我认为

[Id]
  ,[UserName]
  ,[NormalizedUserName]
  ,[Email]
  ,[NormalizedEmail]
  ,[EmailConfirmed]
  ,[PasswordHash]
  ,[SecurityStamp]
  ,[ConcurrencyStamp]
  ,[PhoneNumber]
  ,[PhoneNumberConfirmed]
  ,[TwoFactorEnabled]
  ,[LockoutEnd]
  ,[LockoutEnabled]
  ,[AccessFailedCount]
  ,[FirstName]
  ,[SecondName]
  ,[Company]
  ,[CompanyAdress]
  ,[CompanyEmail]
  ,[CompanyName]
  ,[CompanyPhoneNumber]
  ,**[UserModel_FirstName]**
  ,**[UserModel_SecondName]**
  ,[Discriminator]

我用 ** ** 标记来显示问题,在 .Net 继承的通常规则中,我为这两个 类 取 1 table。但是,我可以为每个 类 创建两个具有 identityUser 属性的 table 吗?

为了完成我的任务,我需要两个 table。我不知道如何实现我的想法

我认为您必须将 IdentityDbContext 与您的自定义模型一起注入。

您可以将模型映射到相应的 table。 example

builder.Entity<UserModel>(b =>
{
    // Primary key
    b.HasKey(u => u.Id);

    //map properties
    b.Property(u => u.FirstName ).HasName("FirstName").IsUnique();
    b.Property(u => u.SecondName ).HasName("SecondName");

    // Maps to the AspNetUsers table
    b.ToTable("AspNetUsers");

});

builder.Entity<UserModelSplit>(b =>
{
    // Primary key
    b.HasKey(u => u.Id);

     //map properties
    b.Property(u => u.UserName ).HasName("UserName").IsUnique();
    b.Property(u => u.NormalizedUserName ).HasName("NormalizedUserName");
...
...
...
    // Maps to the AspNetUsers table
    b.ToTable("AspNetUsersSplit");

});
public class EFDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>  
    {  
        public EFDbContext (DbContextOptions<EFDbContext > options) : base(options)  
        {  

        }  
    }  

例子

public class ApplicationUser : IdentityUser

public class Instructor : ApplicationUser

public class Student : ApplicationUser

默认情况下,Entity Framework 将为 ApplicationUser 创建一个 table 并向其添加鉴别器列。此列将具有三个可能值之一:"ApplicationUser"、"Instructor" 和 "Student"。当EF从这个table中读取时,它会使用这个列来实例化右边的class。这就是所谓的 single-table 继承 (STI) 或 table-per-hierarchy (TPH)。这种方法的主要缺点是所有 classes 的所有属性必须在同一个 table 上表示。例如,如果您要创建一个新的学生,则讲师的列仍会保留在记录中,只是这些值具有空值或默认值。这也意味着您不能在数据库级别对诸如 Instructor 之类的对象强制执行 属性,因为这会阻止保存无法提供这些值的 ApplicationUser 和 Student 实例。换句话说,派生的 classes 上的所有属性都必须可以为空。但是,对于使用视图模型的表单,您仍然可以始终强制执行类似 属性 的要求。

如果您真的想要单独的 table,您可以通过将继承策略更改为所谓的 table-per-type (TPT) 来实现该目标。这将做的是为 ApplicationUser 保留 table,但添加两个额外的 table,每个用于 Instructor 和 Student。但是,所有核心属性、外键等都将位于 ApplicationUser 的 table 上,因为这是定义它们的地方。用于 Instructor 和 Student 的 table 将仅包含在那些 class 上定义的属性(如果有)和用于 ApplicationUser 的 table 的外键。查询时,EF 将执行联接以从所有这些 table 中引入数据,并使用适当的数据实例化适当的 class。一些纯粹主义者更喜欢这种方法,因为它可以使数据库中的数据保持规范化。但是,由于连接,它在查询端必然更重。

最后一句警告,因为这会让人们经常处理身份继承问题。 UserManager class 是一个通用的 class (UserManager)。例如,AccountController 中的默认实例是 UserManager 的实例。因此,如果您使用该实例,则无论 Discriminator 列的值如何,从查询返回的所有用户都将是 ApplicationUser 实例。要获取 Instructor 实例,您需要实例化 UserManager 并将其用于您的 Instructor-related 查询。

Identity in an ASP.NET Core project