我有相互继承的模型,但我很难让流畅的api配置按照我的意愿行事。假设我有一个基类来定义一些核心属性
public class Entity
{
public int Id { get; set; }
public string Title { get; set };
}
Book的子类
public class Book : Entity
{
public int Edition { get; set; }
}
通过这种方式,我可以拥有书籍,杂志,小册子,漫画,演讲等,都可以从我的实体继承,而不必在每个班级上定义关系。
现在我将DbSets添加到DbContext中,就像这样
public class ApplicationDbContext : DbContext
{
public virtual DbSet<Book> Books { get; set; }
public virtual DbSet<Magazine> Magazines { get; set; }
public virtual DbSet<Comic> Comics { get; set; }
}
最后我添加了迁移初始化。
我的迁移现在为每种类型创建单独的表(TPC)。完美。
当我尝试使用流畅的API配置我的基类时出现问题。
我为实体添加配置
class EntityConfiguration : IEntityTypeConfiguration<Entity>
{
public void Configure(EntityTypeBuilder<Entity> builder)
{
builder.HasKey(e => e.Id);
builder.Property(e => e.Title).IsRequired();
}
}
我的想法是,我现在只需要配置基本实体,子类的所有表都应该选择配置。
我将配置添加到DbContext OnModelCreating方法。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new EntityConfiguration());
}
当我添加迁移时,我最终得到了这个
migrationBuilder.CreateTable(
name: "Entity",
columns: table => new
{
Edition = table.Column<int>(nullable: true),
Name = table.Column<string>(nullable: true),
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Discriminator = table.Column<string>(nullable: false),
Title = table.Column<string>(nullable: false),
Frequency = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Entity", x => x.Id);
});
通过尝试配置基类,EF现在沿着TPH路由向下,并使用鉴别器列为Entity创建单个表。
有没有办法避免这种情况?是否甚至可以配置基类并让所有具体表获取基类的配置,但是为子类创建表?
注意:我尝试直接在DbContext OnModelCreating方法中配置实体,而不是使用单独的配置类,但这行为完全相同。
EF Core文档实际上说不支持TPC,这很奇怪,因为它确实为子类创建了单独的表,直到我尝试配置基类为止。
我尝试使用Ignore()来抑制TPH,但这没有效果。
给出的例子不是现实世界。我的实际项目有更多的类,它们都有共同的属性和关系,所以我想避免不得不一遍又一遍地配置相同的东西。
答案 0 :(得分:3)
你说EF Core
在写作时不支持TPC是正确的。
但是,似乎有办法解决这个问题(至少要生成&#39; Up&#39;脚本)。
删除FluentAPI
注册并在实体类的属性中使用Annotations
:
public abstract class Entity
{
[Key]
public int Id { get; set; }
[Required]
public string Title { get; set; }
}
此外,由于TPC是Table Per(Concrete)Class,因此将您从abstract
继承的课程变为优秀。
答案 1 :(得分:0)
EntityConfiguration.cs
public class EntityConfiguration<T> : IEntityTypeConfiguration<T> where T : Entity
{
public virtual void Configure(EntityTypeBuilder<T> builder)
{
builder.HasKey(e => e.Id);
builder.Property(e => e.Title).IsRequired();
}
}
BookConfiguration.cs
public class BookConfiguration : EntityConfiguration<Book>
{
public override void Configure(EntityTypeBuilder<Book> builder)
{
base.Configure(builder);
builder.ToTable("book");
builder.Property(b => b.Edition).HasColumnName("edition");
}
}
采用这种方法,EF核心将只创建“ book”表,而不使用任何区分符。