EF Core Fluent API配置阻止TPC继承

时间:2018-03-08 14:30:16

标签: c# asp.net-core .net-core entity-framework-core asp.net-core-2.0

我有相互继承的模型,但我很难让流畅的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,但这没有效果。

给出的例子不是现实世界。我的实际项目有更多的类,它们都有共同的属性和关系,所以我想避免不得不一遍又一遍地配置相同的东西。

2 个答案:

答案 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)


我总是以这种方式使用TPC模式。 首先,我将“实体”标记为抽象。

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”表,而不使用任何区分符。