使用EF 4.1 Fluent Code First的每类型表继承

时间:2011-06-30 16:13:59

标签: entity-framework entity-framework-4 entity-framework-4.1 entity-framework-6 table-per-type

我有一套相当简单的数据库表,例如:

Vehicle
 Id
 RegNo

Car
 Id (FK of Vehicle.Id)
 OtherStuff

Bike
 Id (FK of Vehicle.Id)
 MoreStuff

我的班级模型正如你所期望的那样:汽车是一个抽象类,然后汽车和自行车是它的子类。

我已按如下方式设置EF4.1 Code First配置:

class VehicleConfiguration : EntityTypeConfiguration<Vehicle> {
    public VehicleConfiguration() {
        ToTable("Vehicles");
        Property(x => x.Id);
        Property(x => x.RegNo);
        HasKey(x => x.Id);
    }
}

class CarConfiguration : EntityTypeConfiguration<Car> {
    public CarConfiguration() {
        ToTable("Cars");
        Property(x => x.OtherStuff);
    }
}

class BikeConfiguration : EntityTypeConfiguration<Bike> {
    public BikeConfiguration() {
        ToTable("Bikes");
        Property(x => x.MoreStuff);
    }
}

然而,当EF试图建立其模型配置时,我遇到了许多奇怪的例外。

目前正在抛出这个:

System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.

从哪个列名获取?它不在我的任何代码或数据库本身。它必须是一些接管控制的惯例。如何指示EF使用每个类型的表?

如果我从我的Vehicle类中删除了“abstract”关键字(我在线上某处进行了一次健全性测试),那么我会得到一个不同的异常,如下所示:

(35,10) : error 3032: Problem in mapping fragments starting at lines 30, 35:EntityTypes AcmeCorp.Car, AcmeCorp.Bike are being mapped to the same rows in table Vehicles. Mapping conditions can be used to distinguish the rows that these types are mapped to.

我显然做了一件非常糟糕的事,但是什么呢?我已经关注了MSDN文档以及我能找到的所有其他TPT + EF4.1文章!

2 个答案:

答案 0 :(得分:8)

您是否阅读了以下文章?

这是一篇涉及以下方法的3部分文章

  1. Table per Hierarchy (TPH): 通过非规范化来启用多态性 SQL模式,并使用包含类型的类型鉴别器列 信息。

  2. Table per Type (TPT): 代表“是一个”(继承) 关系为“有”(外键)关系。

  3. Table per Concrete class (TPC): 放弃多态性和 继承关系完全来自SQL模式。

答案 1 :(得分:8)

当我遇到这个问题时,我发现我有一个未映射的子类。在这个例子中,一些可能的原因是:

  1. 存在另一个子类,例如Bus。这没有映射。
  2. 未映射其中一个子类,例如Car
  3. 在这种情况下,请确保映射每个子类:

    1. 确保子类存在映射,包括ToTable方法调用。
    2. 确保在OnModelCreating期间实际应用了映射。
    3. 如果您无法跟踪此问题,请尝试使用调试程序并在所有映射代码中设置断点。
    4. 或者,如果子类不应该首先映射,请确保使用Ignore方法调用之一忽略它。