【问题标题】:inheritance for EF code first. mixture of TPH and TPT首先继承 EF 代码。 TPH和TPT的混合物
【发布时间】:2012-09-13 13:37:31
【问题描述】:

首先对 EF 代码进行有趣的继承。您认为有一种映射策略可以实现这一目标吗?

所以我有一个名为“Animal”的基本抽象类和来自 Animal 类的 3 个派生类:Fish、Dog 和 UnknownAnimal。 Animal 类有自己的 SQL 表,Fish 和 Dog 分别有 SQL 表 Fish 和 Dog。 UnknownAnimal 没有任何额外的字段,因此此类不需要 SQL 表。为了使它更容易一点,Animal SQL Table 有一个鉴别器列 (TypeName) 来确定 Animal 类型。

SQL 表的代码和图片如下。它既不是 TPH 也不是 TPT,而是一种混合物。我看到的唯一解决方案是使其成为 TPT,通过创建一个 SQL 表“UnknownAnimal”并指向 UnknownAnimal 类来使用该表。但我不想采用这种方式,因为 UnknownAnimal 没有任何额外的属性并且占用了 SQL 服务器中的空间(不多)。

带有集成 Nunit 测试甚至数据库 .bak 文件的完整测试项目的代码。 https://bitbucket.org/RomeoQNgo/efinheritancetest/downloads

我尝试了 TPT,但这需要一个额外的 UnknownAnimal SQL 表。这意味着如果我有另一个类,如 UnknownAnimal(继承自 Animal,但没有额外的属性),那么我必须为它创建一个新表。一种简单的方法是在 Animal SQL 表中设置一个称为 TypeName 之类的鉴别器字段,并让它确定类类型。但是我不想使用 TPH,因为如果有更多的动物类型具有该动物独有的新属性(例如具有 TrunkLength 等属性的大象),那么我们必须在 Animals SQL 表中创建一个新列,而我没有除非没有可能,否则想走这条路。

所以我想将 TPH 和 TPT 结合起来,它们使用鉴别器字段 (TypeName) 来确定类类型和该类特有的动物额外属性的额外表。我想使用 Code First,不想为此使用任何 EDMX 文件。

我想知道目前使用 EF Code First 是否有任何好的方法。提前感谢您的帮助。

public interface IEntity2
{
    string Creator { get; set; }
}

public interface IEntity
{
    int Id { get; set; }
    string DisplayName { get; set; }
}

[Table("Animals")]
public abstract class Animal : IEntity, IEntity2
{
    public virtual int Id { get; set; }
    public virtual string DisplayName { get; set; }
    public virtual int TotalLegs { get; set; }
    public string Creator { get; set; }
}

[Table("UnknownAnimals")]
public class UnknownAnimal : Animal
{
    int test { get { return 1; } }
}

[Table("Fishes")]
public class Fish : Animal
{
    public virtual int WaterType { get; set; }
}

[Table("Dogs")]
public class Dog : Animal
{
    public virtual int FurLength { get; set; }
}

数据库图为:

【问题讨论】:

    标签: entity-framework ef-code-first


    【解决方案1】:

    不知何故,拥有一个UnknownAnimal 类似乎并不正确(尽管我意识到它只是对你的现实生活代码的抽象)。从语义上讲,未知动物是Animal,但它还没有类型(还没有?)。通过使Animal 类不抽象,将其存储为Animal 可能更好地反映现实。这样做,您就不需要UnknownAnimal 表,并且仍然不需要鉴别器列。

    但是您永远无法轻松地仅从数据库中获取UnknownAnimals,因为context.Animals.OfType<Animal>() 返回所有动物。 [就我个人而言,我更喜欢只将继承树的叶子作为具体类型,但这可能是一些先天的心理缺陷。]

    对我来说,问题是:UnknownAnimal 本身就是一种类型吗?如果是这样,请使用该类型并将相对无用的表视为理所当然(以后可能会开发自己的字段)。如果不是,继承可能不是这里的正确模型,您应该使用组合(有人认为总是比继承更好)。

    【讨论】:

    • 非常感谢 Gert 的回复。
    • 不小心按了 Enter 而不是 Shift+Enter。我不得不承认我的比喻很糟糕。 :) 我正在将我们的代码先从 EF .edmx 文件升级到 EF 代码,然后再升级到 EF 代码。以前的版本工作正常,但首先是代码。我似乎找不到有效的映射策略,不确定是因为我对 EF-CF 太陌生,还是代码中不存在此类功能(可能是新功能)。除非别无选择,否则我试图不对数据库进行任何更改/牺牲。
    • 您可以在代码优先中执行此操作。你想坚持的模型是什么?与“无用”表的映射是您提供的类所获得的。您似乎找不到什么?
    • 我是 EF Code 的新手,并试图进一步了解它。是只有 3 种型号,TPH、TPT 和 TPC 还是更多?我们可以把它们混合起来吗?使用 EDMX 文件,我们可以有一个从父类继承的类,并使用鉴别器来确定类类型,如果它除了父类的属性之外没有任何额外的属性但同时没有任何额外的属性,则无需为其创建 SQL 表有时我们也可以从同一个父类继承另一个具有额外属性的类,我们可以将额外属性映射到另一个 SQL 表,同时将父类保留在它自己的 SQL 表中。
    • 字符用完了..在代码中,我们可以使用鉴别器字段来告诉类类型并告诉它不要同时将额外的子类(无属性)映射到 SQL 表能够将其他子类(具有额外属性)映射到自己的表(即具有额外属性的子类a映射到SQL表A,子类B与SQL表B,而没有额外属性的子类C是未映射到任何 SQL 表等。)非常感谢您提前提供的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-04
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多