基本类型的自定义鉴别器 = 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 中的每个实体类型(Event
和 Appointment
)都必须有一个 属性 作为 鉴别器 。
如果您没有为 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"
}
我想使用自定义鉴别器实现 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 中的每个实体类型(Event
和 Appointment
)都必须有一个 属性 作为 鉴别器 。
如果您没有为 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"
}