使用表格继承的 Entity Framework 模型

3
当我在Entity Framework中使用Table-per-Type继承定义模型时,如果我有一个名为person的基类/表(非抽象),以及两个子实体和表adult和child,在创建了一个child之后,我如何将同一对象转换为adult? 一旦转换为adult,应删除child记录,但person表中的基类数据应保留。
2个回答

4
这是不可能的。这是一个类似于此处的问题。实体已经存在且其类型是不可变的。唯一的方法是删除子实体(即两个表中的记录)并创建新的成人实体(即两个表的新记录)。
这根本不像继承的情况。
编辑:
有关继承的评论是针对你提到的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 ,并创建一个新的,但原始对象保持不变 - 只有关系改变。

我有一个名为Datasource的基类和一些派生类:XmlSource、DelimitedSource、ServiceSource等。每个派生类都有特定的属性,而它们都共享通用字段:名称、描述等。你是说从在数据库中存储数据的角度来看,这不像继承的情况吗?我也考虑过将每个派生类的属性序列化并存储在Datasource表中,但我现在更愿意使用表而不是XML。在我的情况下,用户可以将Datasource类型从XML更改为Delimited,这就是我的问题所在。 - mservidio
谢谢您更新的回答。我喜欢您的方法。我最初没有想到过这种方式,尽管我肯定认为这样做更好。 - mservidio

3

我不会在EF中这样做,因为使用继承后,您已经创建了一个面向对象的抽象层来处理表关系,这不允许您从不同类型进行转换。在面向对象编程中,您无法像这样实现:

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);

然而,在你的代码中,你需要确保在这一行之后不再使用子对象,并且很可能需要刷新或从上下文中删除它(对此并不完全确定)。


我喜欢你的想法。为了更进一步,我可以使用泛型将派生对象转换为其基类,然后实例化一个新的派生类。当然,派生类属性总是会丢失,因为它们是特定于子类的,但这没关系。此外,我可以使用泛型从数据库中删除旧的派生对象和记录,并创建一个新的带有新派生类的对象。 - mservidio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接