使用TPH的实体框架的多级继承

本文关键字:多级 继承 框架 实体 TPH 使用 | 更新日期: 2023-09-27 18:08:09

我正在使用实体框架在现有遗留数据库上的新项目中创建每个继承数据模型的表。这意味着我们不拥有数据库,因此我需要一个不涉及向OrderDiscount表添加列的解决方案。

我的数据模型中有以下结构:

       ┌────── (abstract) OrderDiscountBase ──────┐
       │                                          │
       │                                          │
SaleOrderDiscount          ┌─── (abstract) SellerOrderDiscountBase ───┐
                           │                                          │
                           │                                          │
                FreeShippingOrderDiscount                 PercentageValueOrderDiscount

存在一个预先存在的鉴别符列来区分具体类型。它被称为DiscountType,可以保存PercentageOffPromoDiscount, FreeShippingPromoDiscountSaleDiscount的值。

我的项目中有以下映射,不幸的是,它不能工作。

private void ConfigureOrderDiscountEntity(EntityTypeConfiguration<OrderDiscountBase> entity)
{
    entity
        .HasKey(orderDiscount => orderDiscount.Id)
        .Map<SaleOrderDiscount>(
            configuration => configuration.Requires("DiscountType").HasValue(OrderDiscountTypes.Sale))
        .Map<PercentageValueOrderDiscount>(
            configuration => configuration.Requires("DiscountType").HasValue(OrderDiscountTypes.PercentageOff))
        .Map<FreeShippingOrderDiscount>(
            configuration => configuration.Requires("DiscountType").HasValue(OrderDiscountTypes.FreeShipping))
        .ToTable(tableName: "OrderDiscount", schemaName: "Orders")
        ;
}

我看到的例外是:

EntityTypes SellerOrderDiscountBase、SaleOrderDiscount、FreeShippingOrderDiscount、PercentageValueOrderDiscount被映射到表OrderDiscountBase中的相同行。映射条件可用于区分这些类型映射到的行。

我已经看到人们在旧版本的实体框架中通过添加第二个鉴别符列来解决这个问题,但是,正如我所说,我不能对数据库进行更改。

我要求EF做的事情听起来并不困难,所以我假设我刚刚配置了我的实体不正确。

使用TPH的实体框架的多级继承

绝对适合我在EF 6.x:

public abstract class TPHBase
{
    public int ID { get; set; }
    public string CommonProperty { get; set; }
}
public class TPHChild1 : TPHBase
{
    public string Child1Property { get; set; }
}
public abstract class TPHChild2 : TPHBase
{
    public int? Child2Property { get; set; }
}
public class TPHChild3 : TPHChild2
{
    public int? Child3Property { get; set; }
}
public class TPHChild4 : TPHChild2
{
    public int? Child4Property { get; set; }
}
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
    modelBuilder.Entity<TPHBase>()
            .ToTable( "TPHBase" )
            .Map<TPHChild1>( m => m.Requires( "Dyskryminator" ).HasValue( "c1" ) )
            .Map<TPHChild3>( m => m.Requires( "Dyskryminator" ).HasValue( "c3" ) )
            .Map<TPHChild4>( m => m.Requires( "Dyskryminator" ).HasValue( "c4" ) );
    ...

实体被成功持久化,然后从数据库中检索。