0

Я использую ASP.NET Identity 2 в проекте MVC5 и есть 2 типа пользовательских классов: Student и Coordinator, как показано ниже. С другой стороны, я попытался выполнить подход TPH (Table Per Hierarchy), чтобы использовать один и тот же объект для обоих типов пользователей.Как использовать TPH (таблица для иерархии) с идентификатором ASP.NET 2

public class Student : ApplicationUser 
{ 
    public int? Number { get; set; } 
} 


public class Coordinator : ApplicationUser 
{ 
    public string Room { get; set; } 
} 


public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, 
    ApplicationUserRole, ApplicationUserClaim>, IUser<int> 
{ 
    //Custom Properties 
    public string Name { get; set; } 

    public string Surname { get; set; } 

    //code omitted for brevity 
} 

Как ApplicationUser уже унаследовали от IdentityUser, я не создавал его как abstract класса и не добавить его к моему DbContext, как показано ниже:

public DbSet<ApplicationUser> ApplicationUsers { get; set; } 

С другой стороны, существует другое лицо, имеющее Student (не ApplicationUser) в качестве навигационного свойства, показанного ниже:

public class Grade 
{ 
    [Key] 
    public int Id { get; set; } 

    public int Grade { get; set; } 

    //Navigation properties =========================== 
    public virtual Experiment Experiment { get; set; } 

    public virtual Student Student { get; set; } 

    //public virtual ApplicationUser User { get; set; } 
    //================================================= 
} 

}

Однако при добавлении DbSet к DbContext я встретил «Несколько наборов объектов для каждого типа не поддерживаются. Наборы объектов «ApplicationUsers» и «Users» могут содержать экземпляры типа «Xxxx.ApplicationUser». « Ошибка. Итак, есть ли какая-либо ошибка в отношении подхода выше? Должен ли я использовать DbSet в DbContext, и я должен добавить ApplicationUser как навигационная свойство объекта Grade Любая помощь будет оценена ...

+0

@ChrisPratt Есть ли у вас какие-либо идеи относительно этой проблемы? –

+0

@DavidG Не могли бы вы взглянуть на эту проблему, поскольку раньше у вас было мнение относительно моего подобного вопроса? Спасибо ... –

ответ

1

Вы должны быть в состоянии сделать это без добавления ApplicationUsersDbSet к вашему DbContext, так же, как это:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> 
{ 
    public DbSet<Student> Students { get; set; } 
    public DbSet<Coordinator> Coordinators { get; set; } 
    public DbSet<Grade> Grades { get; set; } 
    ... 
} 

И это нормально используйте тип Student в свойстве навигации вашего Grade лица, вы sho uldn't должен использовать ApplicationUser.

Проверьте, что ваша база данных синхронизирована с вашей моделью. Вы используете миграции EF? Ваши таблицы в файлах миграции должны выглядеть так: (обратите внимание на поле Discriminator в таблице AspNetUsers и поля и Room.Это является доказательством применения TPH к созданию таблицы. Кроме того, в таблицу не были включены таблицы для Student или Coordinator миграция.)

 CreateTable(
      "dbo.AspNetUsers", 
      c => new 
       { 
        Id = c.String(nullable: false, maxLength: 128), 
        Name = c.String(), 
        Surname = c.String(), 
        Email = c.String(maxLength: 256), 
        EmailConfirmed = c.Boolean(nullable: false), 
        PasswordHash = c.String(), 
        SecurityStamp = c.String(), 
        PhoneNumber = c.String(), 
        PhoneNumberConfirmed = c.Boolean(nullable: false), 
        TwoFactorEnabled = c.Boolean(nullable: false), 
        LockoutEndDateUtc = c.DateTime(), 
        LockoutEnabled = c.Boolean(nullable: false), 
        AccessFailedCount = c.Int(nullable: false), 
        UserName = c.String(nullable: false, maxLength: 256), 
        Room = c.String(), 
        Number = c.Int(), 
        Discriminator = c.String(nullable: false, maxLength: 128), 
       }) 
      .PrimaryKey(t => t.Id) 
      .Index(t => t.UserName, unique: true, name: "UserNameIndex"); 

     CreateTable(
      "dbo.Grades", 
      c => new 
       { 
        Id = c.Int(nullable: false, identity: true), 
        GradeValue = c.Int(nullable: false), 
        Student_Id = c.String(maxLength: 128), 
       }) 
      .PrimaryKey(t => t.Id) 
      .ForeignKey("dbo.AspNetUsers", t => t.Student_Id) 
      .Index(t => t.Student_Id); 

enter image description here

Если таблицы не похожи на них, попробуйте отменить в пустую базу данных, удаляя миграции и генерируя их снова, и, наконец, обновление базы данных с хорошей миграции ,

Я создал фиктивный проект MVC с вашими сущностями и только те три DbSets в DbContext, сгенерировал миграции и создал таблицы базы данных и запустил следующий тестовый код (по методу индекса контроллера по умолчанию).Данные были правильно сохранены в базе данных:

public void Test() 
    { 
     using (var context = new ApplicationDbContext()) 
     { 
      var student = new Student 
      { 
       Id = "12345", 
       Name = "John", 
       Number = 123, 
       UserName = "Johnny", 
       Email = "[email protected]" 
      }; 
      context.Students.Add(student); 
      context.SaveChanges(); 
     } 

     using (var context = new ApplicationDbContext()) 
     { 
      var student = context.Students.Find("12345"); 
      var grade = new Grade { Id = 333, GradeValue = 90, Student = student }; 
      context.Grades.Add(grade); 
      context.SaveChanges(); 
     } 
    } 

Некоторые вопросы:

  • «Несколько наборов объектов» сообщение об ошибке говорит что-то о «Множества объекта„ApplicationUsers“и„пользователей“». Откуда возникает этот объект «Пользователи», у вас есть пользователи DbSet? Попробуйте удалить его. Или, возможно, вы сделали ошибку копирования-вставки с параметром типа DbSet, что-то вроде написания public DbSet<wrongType> GoodTypeName (бывает).

  • У меня были проблемы с этой декларацией:

    public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>, IUser<int> 
    { ... } 
    

    Так я использовал этот (без параметров типа в базовом классе):

    public class ApplicationUser : IdentityUser 
    { ... } 
    

    Кажется, что по умолчанию реализация проекта MVC с Identity ожидает, что ApplicationUser расширит реализацию IdentityUser без параметров типа. В противном случае возможны ошибки компиляции в нескольких местах, например, при объявлении ApplicationContext и попытке использовать ApplicationUser как параметр типа базового класса IdentityDbContext.

  • Если вы используете базовый класс с параметрами типа, я думаю, что параметр типа TKey должен быть String, а не int, если вы не изменили тип свойства User.Id в своих пользовательских объектах. Возможно, из-за этого вы получаете ошибки? В базе данных поля Id этих объектов имеют тип varchar.

  • Я изменил название Grade собственности GradeValue (Grade не является допустимым именем свойства, потому что это имя класса, я получаю ошибку компиляции).

Если вам это нужно, я могу отправить код макета, который я использовал для проверки этого.

+0

Muchisima gracias Diana, я внимательно прочитал все ваши комментарии. Я изменил тип идентификации из строки в int, и с этой стороны проблем нет. С другой стороны, таблица базы данных имеет то же самое, что и разделитель и пользовательские столбцы, и нет дополнительной таблицы. Значит, все в порядке. Saludos cordiales y muchas gracias otra vez :) –

+0

Добро пожаловать! – Diana

Смежные вопросы