【问题标题】:Multiple levels of inheritance with Entity Framework using TPH使用 TPH 的实体框架的多级继承
【发布时间】:2015-08-14 22:02:25
【问题描述】:

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

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

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

有一个预先存在的鉴别器列来区分具体类型。它称为DiscountType,可以保存PercentageOffPromoDiscountFreeShippingPromoDiscountSaleDiscount 的值。

我的项目中有以下映射,但不幸的是,它不起作用。

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 中的相同行。映射条件可用于区分这些类型映射到的行。

我看到人们在旧版本的 Entity Framework 中通过添加第二个鉴别器列来解决这个问题,但正如我所说,我无法对数据库进行更改。

我要求 EF 做的事情听起来并不难,所以我认为我只是错误地配置了我的实体。

【问题讨论】:

    标签: c# entity-framework tph


    【解决方案1】:

    在 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" ) );
    
        ...
    

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

    我怀疑有些东西比你发布的要多。

    【讨论】:

    • 你是如何为 w.r.t. 的关系建模的。哪个表有外键?当孩子引用其父母时,我无法让您的示例正常工作。
    • @Richiban:孩子和父母?听起来您正在继承类之间进行引用,是吗?在我的示例中,没有父子外键,您也没有在帖子中提及外键。
    • 嗯,我不知道如何或为什么,但我基本上破坏了数据层并重新开始......它奏效了!感谢您的回答,我确信我想做的事情实际上得到了支持,我可以坚持下去。终于到了。
    • @Richiban:如果您一开始就发现出了什么问题,请在此答案或您的问题下写一个简短的注释,以便有人可以从学习中受益。问候。
    • 如何在 linq 查询中直接使用 TPHChild4?即var q= from ch4 in tphchild4 where age&gt;10 select ch4
    猜你喜欢
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    相关资源
    最近更新 更多