Беглое отображение наследования
У меня есть проблема, для которой я не знаю лучшего решения. Надеюсь, кто-то здесь может помочь =)
Что я пытаюсь решить: мы должны вводить пользователей в систему, человека и организацию. Я хочу иметь общую таблицу входа для двоих (т. Е. Пользователь, вероятно, не будет знать, какого типа он пользователь, он просто связан с именем пользователя и паролем). Поэтому я создал таблицу входа в систему для имен пользователей и паролей. Но мне нужно знать, к кому подключен логин, поэтому мне нужна ссылка либо на человека, либо на организацию.
Рассмотрим следующие классы (упрощенно):
public class Login
{
public string Username {get; set;}
public string Password {get;set;}
}
public class LoginPerson : Login
{
public Person Person {get;set;}
}
public class LoginOrg : Login
{
public Organization Organization {get;set;}
}
public class Person
{
public LoginPerson LoginPerson {get;set;}
//Lots of other properties. Removed for simplicity
}
public class Organization
{
public LoginOrg LoginOrg {get;set;}
//Lots of other properties. Removed for simplicity
}
Конфигурация человека настроена следующим образом:
public class PersonConfiguration : EntityTypeConfiguration<Person>
{
public PersonConfiguration()
{
HasRequired(p => p.LoginPerson).WithRequiredPrincipal(p => p.Person);
}
}
Прежде всего, это не работает. Я получаю исключение: "System.Data.EntityCommandCompilationException: System.Data.EntityCommandCompilationException: при подготовке определения команды произошла ошибка. Подробности см. Во внутреннем исключении. ---> System.Collections.Generic.KeyNotFoundException: указанный ключ был отсутствует в словаре.."Итак, мой первый вопрос: почему это не работает? Мой второй вопрос: какая стратегия лучше всего подходит для такого рода наследования? TPT, TPH или TPC?
2 ответа
Решением для моего исключения было установить правильную конфигурацию;-) PersonConfiguration не нужно было включать какую-либо конфигурацию для свойства LoginPerson. Я добавил LoginPersonConfiguration ->
public class LoginPersonConfiguration : EntityTypeConfiguration<LoginPerson>
{
public LoginPersonConfiguration()
{
ToTable("LoginPerson");
HasKey(l => l.Id);
HasRequired(l => l.Person).WithOptional(p => p.LoginPerson).Map(t => t.MapKey("PersonId"));
}
}
И я также должен был добавить Логин в класс DbContext
public class MyDbContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Login> Logins { get; set; }
}
Когда речь заходит о том, какая стратегия лучше, я решил пойти на TPT.
Ну, для начала, ни у кого из ваших сущностей нет ключей. Вам нужен первичный ключ, чтобы заставить их работать. EF использует соглашение, чтобы сделать это, которое является именем класса плюс Id в конце, как PersonId, или вы должны быть явным с атрибутом [Key]
Во-вторых, ваша модель запутанная и довольно круглая. А без первичных ключей невозможно создать ассоциации.
Я запутался, почему у вас есть член, который является LoginPerson в объекте Person, и то же самое для Организации? В любом случае, вам действительно нужно переосмыслить эту модель и выяснить, какие у вас ключи.