我正在使用遗留系统,该系统为特定数量的项目实施TPH。所以当前的结构看起来像这样
Abstract Class 1 Abstract Class 2 Abstract Class 3
| | |
--------- --------- ---------
| | | | | | | | |
T1 T2 T3 T4 T5 T6 T7 T8 T9
因此Type(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(比如Conditional Mapping in Entity Framework - OR operation with TPH)替换BoatId,PlaneId和CarId似乎可能会有效,但在那时我们将进行真正的侵入式架构更改,这实际上不是一个选项而且我是不确定甚至可以工作。基本上我需要一种方法将现有密钥映射到新的层次结构。任何帮助是极大的赞赏。我很茫然,似乎无法找到解决我问题的任何解决方案。
答案 0 :(得分: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
///
}
答案 1 :(得分:0)
问题在于所有这些项目实际上都有一个共同点,但没有办法将所有这些项目收集到一个集合中。
也许你可以在每个层次结构中有类型实现一个通用接口?由于每个层次结构都已经是一个单独的表,因此通过添加公共基类似乎不会获得太多 - 而且似乎不值得麻烦。
答案 2 :(得分:0)
可以根据您在DbSet<>
中定义的DbContext
来定义TPH / TPC约定。例如,您不是为每个派生类型DbSet<>
声明T
,而是仅为每个抽象类型声明DbSet<>
。然后,您可以使用相应的DbSet<>
或所有抽象类分别查询抽象类,并使用基本抽象类型的DbSet<>
。
基本抽象类必须至少定义一个字段,因此Code-First Migrations将为该类型生成一个表。要定义的最合理的字段是PK。但是,由于抽象类之间的PK冲突(正如您在评论中所述),当前数据的迁移将不起作用。
另一种可能性是,当您查询基本抽象类型的DbSet<>
时,实体框架将正确查询所有抽象类型,即使数据库中没有基本抽象类型的表(因为基本抽象类型)没有定义字段)。但是,我之前没有遇到过这种情况,所以我不能肯定地说它是否会起作用。