EF6 - сопоставление внешнего ключа TPH в производных классах с использованием свойства базового класса

c# entity-framework entity-framework-6 single-table-inheritance table-per-hierarchy

Вопрос

Я использую Entity Framework 6.0.2 с существующей базой данных, в которой теги хранятся в одной таблице, которая выглядит так:

  • Id : int, первичный ключ
  • TagType : string, определить тип тега, либо "usertag", либо "movietag"
  • ItemId : int, содержит идентификатор элемента, к которому относится (либо идентификатор пользователя, либо идентификатор фильма)

Следующие классы описывают эту ситуацию:

public class User
{
    public int Id { get; set; }
}

public class Movie
{
    public int Id { get; set; }
}

public abstract class Tag
{
    public int Id { get; set; }
    public int ItemId { get; set; }
}

public class UserTag : Tag
{
    public virtual User User { get; set; }
}

public class MovieTag : Tag
{
    public virtual Movie Movie { get; set; }
}

Как вы можете видеть, мои производные классы имеют свойства навигации, которые поддерживаются значением свойства ItemId в базовом классе. Мое отображение выглядит следующим образом:

public class User
{
    public int Id { get; set; }
}

public class Movie
{
    public int Id { get; set; }
}

public abstract class Tag
{
    public int Id { get; set; }
    public int ItemId { get; set; }
}

public class UserTag : Tag
{
    public virtual User User { get; set; }
}

public class MovieTag : Tag
{
    public virtual Movie Movie { get; set; }
}

Теперь, когда я пытаюсь использовать это сопоставление, используя следующий код, я получаю исключение:

public class User
{
    public int Id { get; set; }
}

public class Movie
{
    public int Id { get; set; }
}

public abstract class Tag
{
    public int Id { get; set; }
    public int ItemId { get; set; }
}

public class UserTag : Tag
{
    public virtual User User { get; set; }
}

public class MovieTag : Tag
{
    public virtual Movie Movie { get; set; }
}

Исключением является:

Unhandled Exception: System.InvalidOperationException: The foreign key component 'ItemId' is not a declared property on type 'UserTag'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property

Да свойство ItemId не объявляется в типе UserTag , но наследуется от базового класса Tag . Мне кажется, что это сопоставление должно быть возможным. Является ли это ошибкой или ограничением в Entity Framework 6?

Принятый ответ

Это ограничение. EF довольно тесно связан с тем, как работает реляционная база данных. То, что вы пытаетесь сделать с точки зрения базы данных, состоит в том, чтобы поставить два ограничения внешнего ключа на один столбец ItemId . Внешнее ограничение в базе данных не является условным, поэтому запись всегда будет использовать оба ограничения независимо от типа тега. Это не то, что вы хотите, потому что такое определение всегда потребует как пользователя, так и фильма с определенным идентификатором для каждого отдельного тега.

Подумайте об этом по-другому. Если он работает так, как вы пытаетесь определить его, не было бы причин, по которым в дочерних сущностях были бы свойства навигации для User и Movie - достаточно было бы иметь одно свойство навигации в родительском. Тот факт, что вы должны определить их в дочерних объектах, потому что они разные для каждого из них, также означает, что вам нужно иметь два разных внешних ключа.

Вы должны иметь отдельный UserId и MovieId в своих конкретных тегах.




Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему