Модель Entity Framework с наследованием таблиц по типам

Когда я определяю модель в Entity Framework с наследованием таблиц по типам, если у меня есть базовый класс / таблица (не абстрактная) с именем person, и две дочерние сущности и таблицы, взрослый и дочерний, после создания дочернего элемента, как бы я взять тот же объект и преобразовать его во взрослый? После преобразования во взрослую запись дочерняя запись должна быть удалена, хотя данные базового класса в таблице людей должны быть сохранены.


person mservidio    schedule 07.09.2011    source источник


Ответы (2)


Это невозможно. Это аналогичная проблема, аналогичная здесь. Просто сущность существует и ее тип неизменен. Единственный способ сделать это - удалить дочерний объект (= записи из обеих таблиц) и создать новый взрослый объект (= новые записи для обеих таблиц).

Это вообще не похоже на сценарий наследования.

Редактировать:

Комментарий о наследовании предназначен для сценария, в котором вы упомянули объекты Person, Adult и Child. В любом случае, как только ваш сценарий позволяет изменить тип, вы должны подумать о другом решении, в котором часть, которая может измениться, будет обрабатываться композицией.

Например:

public class DataSource
{
    public int Id { get; set; }
    public virtual DataSourceFeatures Features { get; set; }
}

public class DataSourceFeatures
{
    [Key, ForeignKey("DataSource")]
    public int Id { get; set; }
    public virtual DataSource DataSource { get; set; }
}

public class XmlDataSourceFeatures : DataSourceFeatures { ... }

public class DelimitedDataSourceFeatures : DataSourceFeatures { ... }

public class ServiceDataSourceFeatures : DataSourceFeatures { ... }

Теперь изменение типа означает удаление зависимого текущего DataSourceFeatures из базы данных и создание нового, но исходный объект остается прежним - изменяется только отношение.

person Ladislav Mrnka    schedule 07.09.2011
comment
У меня есть базовый класс с именем Datasource и несколько производных классов: XmlSource, DelimitedSource, ServiceSource и т. Д. Каждый производный класс имеет определенные свойства, в то время как все они имеют общие поля: имя, описание и т. Д. Вы говорите, что с точки зрения хранения данных в БД это не похоже на сценарий наследования? Я также рассмотрел сериализацию свойств каждого производного класса и сохранение их в таблице Datasource, но я бы предпочел сейчас работать с таблицами, а не с XML. В моем случае пользователь может изменить тип источника данных с XML на разделенный, вот откуда пришел мой вопрос. - person mservidio; 08.09.2011
comment
Спасибо за обновленный ответ. Мне нравится твой подход. Первоначально я не думал об этом так, хотя я определенно думаю, что это работает лучше. - person mservidio; 08.09.2011

Я бы не стал этого делать с EF, потому что с наследованием вы создали объектно-ориентированную абстракцию над связями таблиц, которая не позволяет вам конвертировать из разных типов. В OO вы не можете делать что-то подобное:

Child child = new Child();
Adult grownUp = child;

А потом ожидайте, что ребенок станет взрослым. Вы бы сделали это так:

Child child = new Child();
Adult grownUp = child.GrowUp();

Предполагая, что вы используете SQL Server, вы можете сделать это с помощью хранимой процедуры. Что-то вроде GrowUp (child), и пусть он создаст новую запись в таблице Adult, а также удалит запись в таблице Child, но оставьте Person нетронутым. Вы можете вернуть новый взрослый объект из процедуры. Затем это можно использовать следующим образом:

Adult grownUp = context.GrowUp(child);

Однако вам нужно убедиться в своем коде, что после этой строки вы больше не используете дочерний объект и вам, вероятно, потребуется обновить или удалить его из контекста (не совсем уверен в этом).

person Andreas    schedule 07.09.2011
comment
Мне здесь нравится твое мышление. Чтобы продвинуть эту идею на шаг впереди, я мог бы использовать дженерики для приведения производного объекта к его базовому классу, а затем создать экземпляр нового производного класса. Конечно, свойства производного класса всегда будут потеряны, поскольку они относятся к дочерним классам, но это нормально. Кроме того, я мог бы использовать дженерики для удаления старого производного объекта и записи из базы данных и создания нового с новым производным классом. - person mservidio; 08.09.2011