基于基本类型的自定义鉴别符= null:“但未配置鉴别符值”

时间:2019-07-25 13:13:47

标签: c# .net-core entity-framework-core entity-framework-core-2.2

我想用自定义鉴别器实现TPH(每个层次的表)。这是模型:

public class Event
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Start { get; set; }
}
public class Appointment : Event
{
    public TimeSpan Duration { get; set; }
}

我的自定义鉴别符应该在Duration列中:如果是NULL,则必须是Event,否则是Appointment

但是在创建迁移步骤时出现此错误:

  

实体类型“事件”是层次结构的一部分,但未配置区分值。

我错了什么?以及如何启动和运行鉴别器?


这里是DbContext

public class ApplicationDbContext : DbContext
{
    ...
    public DbSet<Event> Events { get; set; }
    public DbSet<Appointment> Appointments { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        ...
        modelBuilder.Entity<Event>()
            .HasDiscriminator<TimeSpan?>(nameof(Appointment.Duration))
            .HasValue(null)
            ;
    }
}

1 个答案:

答案 0 :(得分:1)

您收到的错误最初是因为 Discriminator 的值不能为null。但是实际上还有另一个问题使其无法使用。

TPH中的每种实体类型(EventAppointment)必须具有 Discriminator 的属性。
如果您未为 Discriminator 指定任何配置,则默认使用具有字符串类型的名为 Discriminator 的属性。此属性存储实体类型的名称,并用于检查行映射到的类型。

您可以保留 Discriminator 的配置(保留默认行为),也可以配置如下自定义项:

public class Event
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Start { get; set; }
}
public class Appointment : Event
{
    public TimeSpan Duration { get; set; }
}

public class ApplicationDbContext : DbContext
{
    ...
    public DbSet<Event> Events { get; set; }
    public DbSet<Appointment> Appointments { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        ...
        modelBuilder.Entity<Event>()
            .HasDiscriminator<int>("discriminator")
            .HasValue<Event>(1)
            .HasValue<Appointment>(2);
    }
}

注意:如果 Discriminator 的类型不是字符串,则对于层次结构中的每个实体类型,必须指定一个鉴别符值。 (如上面的代码所示)

但是,如果 Discriminator 的类型为字符串,则可以自动用实体类型名称填充。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    ...
    modelBuilder.Entity<Event>()
        .HasDiscriminator<string>("discriminator")
        .HasValue("e"); // "e" is the value of discriminator for Event type. 
        // we don't need to specify another value for Appointment type. it defaults 
        // to "Appointment"
}