基本类型的自定义鉴别器 = null:"but does not have a discriminator value configured"

Custom Discriminator on base type = null: "but does not have a discriminator value configured"

我想使用自定义鉴别器实现 TPH(Table 每个层次结构)。以下是型号:

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.

但我在创建迁移步骤时遇到此错误:

The entity type 'Event' is part of a hierarchy, but does not have a discriminator value configured.

我做错了什么?我怎样才能启动鉴别器并 运行?


这是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)
            ;
    }
}

你得到的错误最初是因为 Discriminator 的值不能为空。但实际上还有另一个问题使它无法工作。

TPH 中的每个实体类型(EventAppointment)都必须有一个 属性 作为 鉴别器
如果您没有为 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的type是string,那么可以自动填充entity type name.

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"
}