Как создать две таблицы различий с IdentityUser - PullRequest
0 голосов
/ 14 мая 2019

Проект в ядре 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 таблицу для этих двух классов. Однако можно ли создать две таблицы для каждого из классов со свойствами identityUser.

для моей задачи мне нужны две таблицы. Я не знаю, как реализовать мою идею

1 Ответ

1 голос
/ 14 мая 2019

Я думаю, что вы должны ввести свой IdentityDbContext с вашими моделями.

Вы можете сопоставить свои модели с соответствующими таблицами. пример

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 и добавит в нее столбец Discriminator.Этот столбец будет иметь одно из трех возможных значений: «ApplicationUser», «Instructor» и «Student».Когда EF читает из этой таблицы, он будет использовать этот столбец для создания экземпляра нужного класса.Это то, что известно как наследование одной таблицы (STI) или, альтернативно, как таблица на иерархию (TPH).Основным недостатком этого подхода является то, что все свойства для всех классов должны быть представлены в одной таблице.Например, если вы создаете нового ученика, столбцы для инструктора все равно будут в записи, только с нулевыми значениями или значениями по умолчанию для этих значений.Это также означает, что вы не можете принудительно установить свойство для чего-то наподобие Instructor на уровне базы данных, так как это предотвратит сохранение экземпляров ApplicationUser и Student, которые не могут предоставить эти значения.Другими словами, все ваши свойства в ваших производных классах должны быть обнуляемыми.Тем не менее, вы всегда можете применить что-то вроде свойства, необходимого для формы с помощью моделей представлений.

Если вы действительно хотите иметь отдельные таблицы, вы можете достичь этой цели, изменив стратегию наследования начто называется таблицей за тип (TPT).Для этого нужно сохранить таблицу для ApplicationUser, но добавить две дополнительные таблицы, по одной для инструктора и ученика.Однако все свойства ядра, внешние ключи и т. Д. Будут находиться в таблице для ApplicationUser, поскольку именно здесь они определены.Таблицы для Инструктора и Студента будут содержать только свойства, определенные для этих классов (если таковые имеются) и внешний ключ к таблице для ApplicationUser.При запросе EF будет затем выполнять соединения для получения данных из всех этих таблиц и создания экземпляров соответствующих классов с соответствующими данными.Некоторым пуристам этот подход нравится больше, поскольку данные нормализуются в базе данных.Тем не менее, на стороне запроса он обязательно тяжелее из-за объединений.

Последнее слово предостережения, так как это заставляет людей постоянно иметь дело с наследованием с помощью Identity.Класс UserManager является универсальным классом (UserManager).Например, экземпляром по умолчанию в AccountController является экземпляр UserManager.В результате, если вы используете этот экземпляр, все пользователи, возвращаемые из запросов, будут экземплярами ApplicationUser, независимо от значения столбца Discriminator.Чтобы получить экземпляры Instructor, вам нужно создать экземпляр UserManager и использовать его для запросов, связанных с Instructor.

Удостоверение в проекте ASP.NET Core

...