首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于TPH的实体框架多级继承

基于TPH的实体框架多级继承
EN

Stack Overflow用户
提问于 2015-08-02 02:44:27
回答 3查看 1.1K关注 0票数 10

我正在使用一个遗留系统,它为一定数量的项目实现了TPH。因此,当前的结构如下所示

代码语言:javascript
复制
 Abstract Class 1     Abstract Class 2     Abstract Class 3
         |                    |                    |
     ---------            ---------            ---------
    |    |    |          |    |    |          |    |    |
    T1   T2   T3        T4    T5   T6         T7   T8   T9

因此类型(T*)是所有表的鉴别器,但由于某些类型共享公共列,因此存在大量不同的表。问题是,所有这些项目实际上共享一个小的共同点,但没有办法将所有这些项目收集到一个集合中。实际上,层次结构实际上应该看起来更像这样。

代码语言:javascript
复制
          --------------- Base Abstract 1 ---------- 
         |                    |                    |
 Abstract Class 1     Abstract Class 2     Abstract Class 3
         |                    |                    |
     ---------            ---------            ---------
    |    |    |          |    |    |          |    |    |
    T1   T2   T3        T4    T5   T6         T7   T8   T9

因此,从本质上讲,我们有一个TPT,其中每个类型的每个表都是一个TPH。对于一个真实世界的例子,这是我们需要的。

代码语言:javascript
复制
          ---------------  Vehicle   --------------- 
         |                    |                    |
        Car                 Boat                 Plane
         |                    |                    |
     ---------            ---------            ---------
    |    |    |          |    |    |          |    |    |
   BMW Toyota Fiat      T4   T5   T6         T7    T8   T9

显然,最初的设计存在一些设计缺陷,没有人预料到需要在不查询3个不同表的情况下获取所有车辆的列表。所以我的问题是,在现有的结构下,有没有办法将这个新的层次结构添加到实体框架中。我在想像这样的事情

代码语言:javascript
复制
  Vehicle
  -------
  VehicleId
  TypeId (Boat, Plane, Car, etc)
  ItemFK (BoatID, PlaneId, CarId)

这个是可能的吗?有没有办法将这些映射到实体框架中?我似乎不能正确地匹配它们。如果我们将BoatId、PlaneId和CarId替换为VehicleId (如Conditional Mapping in Entity Framework - OR operation with TPH),似乎可以工作,但在这一点上,我们将进行真正侵入性的模式更改,这并不是一个真正的选择,我甚至不确定这是否会起作用。本质上,我需要一种方法来将现有的键映射到新的层次结构中。任何帮助都是非常感谢的。我不知所措,似乎找不到任何解决方案来回答我的问题。

EN

回答 3

Stack Overflow用户

发布于 2016-07-03 12:30:02

你可以使用这个结构

代码语言:javascript
复制
 public class Vehicle
    {
        [Key]
        public int Id { set; get; }

        ///
        // common properties
        ///

        public Car Car { set; get; }
        public Boat Boat { set; get; }
        public Plane Plane { set; get; }
    }

    public class Car
    {
        [Key, ForeignKey("Vehicle")]
        public int VehicleId { set; get; }
        public Vehicle Vehicle { set; get; }

        ///
        // Car properties
        ///
    }

    public class Boat
    {
        [Key, ForeignKey("Vehicle")]
        public int VehicleId { set; get; }
        public Vehicle Vehicle { set; get; }

        ///
        // Boat properties
        ///
    }

    public class Plane
    {
        [Key, ForeignKey("Vehicle")]
        public int VehicleId { set; get; }
        public Vehicle Vehicle { set; get; }

        ///
        // Plane properties
        ///
    }
票数 1
EN

Stack Overflow用户

发布于 2015-08-06 14:35:53

问题是,所有这些项实际上都有一个小的共同点,但是没有办法将所有这些项都收集到一个集合中。

也许你可以让每个层次结构中的类型实现一个公共接口?由于每个层次结构都已经是一个单独的表,因此通过添加一个公共基类似乎不会获得太多好处--而且似乎不值得这么麻烦。

票数 0
EN

Stack Overflow用户

发布于 2015-09-29 08:13:16

可以基于您在DbContext中定义的DbSet<>来定义TPH/TPC约定。例如,您只需为每个抽象类型声明一个DbSet<>,而不是为每个派生类型T声明一个DbSet<>。然后,您可以使用相应的DbSet<>单独查询抽象类,也可以使用基本抽象类型的DbSet<>查询所有抽象类。

基抽象类必须至少定义一个字段,以便Code-First Migrations将为该类型生成一个表。要定义的最符合逻辑的字段应该是主键。然而,由于抽象类之间的PK冲突(如您在注释中所述),当前数据的迁移将无法工作。

另一种可能性是,当您查询基本抽象类型的DbSet<>时,实体框架将正确地查询所有抽象类型,即使数据库中没有用于基本抽象类型的表(因为基本抽象类型没有定义字段)。然而,我以前没有遇到过这种情况,所以我不能肯定地说它是否会工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31765006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档