10

我正在使用一个为一定数量的项目实现 TPH 的遗留系统。所以当前的结构看起来像这样

 Abstract Class 1     Abstract Class 2     Abstract Class 3
         |                    |                    |
     ---------            ---------            ---------
    |    |    |          |    |    |          |    |    |
    T1   T2   T3        T4    T5   T6         T7   T8   T9

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

          --------------- Base Abstract 1 ---------- 
         |                    |                    |
 Abstract Class 1     Abstract Class 2     Abstract Class 3
         |                    |                    |
     ---------            ---------            ---------
    |    |    |          |    |    |          |    |    |
    T1   T2   T3        T4    T5   T6         T7   T8   T9

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

          ---------------  Vehicle   --------------- 
         |                    |                    |
        Car                 Boat                 Plane
         |                    |                    |
     ---------            ---------            ---------
    |    |    |          |    |    |          |    |    |
   BMW Toyota Fiat      T4   T5   T6         T7    T8   T9

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

  Vehicle
  -------
  VehicleId
  TypeId (Boat, Plane, Car, etc)
  ItemFK (BoatID, PlaneId, CarId)

这可能吗?有没有办法在实体框架中映射这些?我似乎无法正确匹配它们。如果我们用 VehicleId 替换 BoatId、PlaneId 和 CarId (如实体框架中的条件映射 - 或使用 TPH 的操作) ,似乎它可能会起作用,但那时我们将进行真正侵入性的模式更改,这并不是真正的选项,我不确定这是否可行。本质上,我需要一种将现有键映射到新层次结构的方法。任何帮助是极大的赞赏。我很茫然,似乎找不到任何可以回答我问题的解决方案。

4

3 回答 3

1

你可以使用这个结构

在此处输入图像描述

 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
        ///
    }
于 2016-07-03T04:30:02.073 回答
0

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

基本抽象类必须至少定义一个字段,以便 Code-First Migrations 将为该类型生成一个表。要定义的最合乎逻辑的字段是 PK。但是,由于抽象类之间的 PK 冲突(如您在评论中所述),当前数据的迁移将不起作用。

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

于 2015-09-29T00:13:16.143 回答
0

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

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

于 2015-08-06T06:35:53.307 回答