【问题标题】:Entity Framework core 3.1.1 Multilevel InheritanceEntity Framework core 3.1.1 多级继承
【发布时间】:2020-02-03 15:38:43
【问题描述】:

运行 add-migration (EF core 3.1.1) 时抛出异常:

CLR 属性“DiscriminatorLevel2Id”不能添加到实体类型“CustomerBase”,因为它是在 CLR 类型“InternalCustomer”上声明的

下图显示了所需的层次结构(简要):

映射如下:

// Discriminator (Level 1)
modelBuilder.Entity<CustomerBase>()              
            .HasDiscriminator(b => b.CustomerTypeId)
            .HasValue<InternalCustomer>((int)CustomerType.Internal)
            .HasValue<ExternalCustomer>((int)CustomerType.External);

// Discriminator (Level 2)
modelBuilder.Entity<InternalCustomer>()
         .HasDiscriminator(b => b.DiscriminatorLevel2Id)
         .HasValue<VIPCustomer>((int)DiscriminatorLevel2.VIP)
         .HasValue<RegularCustomer>((int)DiscriminatorLevel2.Regular);

Entity Framework Core 3.1.1 是否支持“多级继承 TPH”?

【问题讨论】:

  • 多级鉴别器 - 没有。具有共同鉴别器的多级继承 - 是的。
  • 感谢Ivan Stove,“多级继承与共同鉴别器”是如何实现的,上面的例子中需要做哪些改变?

标签: c# entity-framework-core table-per-hierarchy


【解决方案1】:

这是可能的,但在根抽象级别使用单个共享鉴别器,其中包含所有可能的可创建(非抽象)直接或间接派生实体的值。

应用于您的示例需要删除DiscriminatorLevel2 属性(列),从CustomerType 枚举中删除Internal(假设InternalCustomer 是抽象的)并将RegularVIP 合并到其中,例如像这样:

型号:

public abstract class CustomerBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CustomerTypeId { get; set; }
}

public abstract class InternalCustomer : CustomerBase
{
    public decimal Points { get; set; }
}

public class RegularCustomer : InternalCustomer
{
    public int PartnerId { get; set; }
}

public class VIPCustomer : InternalCustomer
{
    public string CardNo { get; set; }
}

public class ExternalCustomer : CustomerBase
{
}

public enum CustomerType { External, Regular, VIP }

配置:

modelBuilder.Entity<CustomerBase>()
    .HasDiscriminator(b => b.CustomerTypeId)
    .HasValue<ExternalCustomer>((int)CustomerType.External)
    .HasValue<VIPCustomer>((int)CustomerType.VIP)
    .HasValue<RegularCustomer>((int)CustomerType.Regular);

modelBuilder.Entity<InternalCustomer>();

当您想查询InternalCustomer 派生实体时,可以使用db.Set&lt;InternalCustomer&gt;()db.Set&lt;CustomerBase&gt;().OfType&lt;InternalCustomer&gt;(),EF Core 将应用类似于t.CustomerTypeId IN (1,2) 的过滤器,即IN 子句将包含所有的鉴别器值列表派生自InternalCustomer 的最终实体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 2018-12-01
    • 2020-06-08
    • 1970-01-01
    相关资源
    最近更新 更多