EF Core Fluent API 配置防止 TPC 继承 [英] EF Core Fluent API Configuration Prevents TPC Inheritance

查看:29
本文介绍了EF Core Fluent API 配置防止 TPC 继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有相互继承的模型,但我正在努力使流畅的 api 配置按照我想要的方式运行.假设我有一个定义一些核心属性的基类

I have models which inherit from each other, but I am struggling to get the fluent api configuration to behave as I want it to. Let's say I have a base class which defines some core properties

public class Entity
{
   public int Id { get; set; }
   public string Title { get; set };
}

还有一个 Book 的子类

And a subclass for Book

public class Book : Entity
{
    public int Edition { get; set; }
}

这样我就可以拥有书籍、杂志、小册子、漫画、演讲等,所有这些都继承自我的实体,而不必在每个类上定义关系.

This way I can have books, magazines, pamphlets, comics, speeches etc, all inheriting from my Entity, and not have to define the relationship on every class.

现在我像这样将我的 DbSet 添加到 DbContext

Now I add my DbSets to the DbContext like this

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).完美.

My migration now creates separate tables (TPC) for each type. Perfect.

当我尝试使用 fluent API 配置我的基类时,问题就出现了.

The problem comes when I try to configure my base class using fluent API.

我为实体添加配置

class EntityConfiguration : IEntityTypeConfiguration<Entity>
{
    public void Configure(EntityTypeBuilder<Entity> builder)
    {
       builder.HasKey(e => e.Id);
       builder.Property(e => e.Title).IsRequired();
    }
} 

这个想法是我现在只需要配置基本实体,子类的所有表都应该选择配置.

The idea being that I will now only need to configure the base Entity, and all tables for the subclasses should pick up the configuration.

我将我的配置添加到 DbContext OnModelCreating 方法中.

I add my configuration to the DbContext OnModelCreating method.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   base.OnModelCreating(modelBuilder);
   modelBuilder.ApplyConfiguration(new EntityConfiguration());
}

当我添加迁移时,我最终得到了这个

When I add-migration, I end up with this

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 路线走下去,并为具有鉴别器列的实体创建单个表.

By trying to configure the base class, EF is now going down the TPH route, and creating a single table for Entity with a discriminator column.

有没有办法避免这种情况?甚至可以配置基类并让所有具体的表获取基类的配置但为子类创建表吗?

Is there a way to avoid this? Is it even possible to configure the base class and have all concrete tables pick up the configuration on the base class but create tables for the subclasses?

注意:我已经尝试在 DbContext OnModelCreating 方法中直接配置实体,而不是使用单独的配置类,但这行为是一样的.

NOTE: I have tried configuring the Entity directly in the DbContext OnModelCreating method, instead of using a separate configuration class, but this behaves just the same.

EF Core 文档实际上说不支持 TPC,这很奇怪,因为它确实为子类创建了单独的表,直到我尝试配置基类.

The EF Core docs actually say TPC is not supported, which is strange because it does create separate tables for the subclasses until I try to configure the base class.

我曾尝试使用 Ignore() 来抑制 TPH,但这没有效果.

I have tried using Ignore() to suppress the TPH but this has no effect.

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

Example given is not real-world. My actual project has many more classes which all have common properties and relationships, so I want to avoid having to configure the same things over and over again.

推荐答案

您说的是对的,EF Core 在撰写本文时不支持 TPC.

You are correct in saying that EF Core does not support TPC as of writing.

不过,似乎有办法解决这个问题(至少可以生成Up"脚本).

However, there does appear to be a way to get around this (for generating the 'Up' script at least).

删除 FluentAPI 注册并在实体类的属性上使用 Annotations:

Remove the FluentAPI registrations and use Annotations on the Entity class's properties:

public abstract class Entity
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string Title { get; set; }
}

另外,因为 TPC 是 Table Per (Concrete) Class,所以最好让你从 abstract 继承的类.

Also, because TPC is Table Per (Concrete) Class, it's good practice to make the class you're inheriting from abstract.

这篇关于EF Core Fluent API 配置防止 TPC 继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆