首页 > 解决方案 > 迁移中不生成继承的子表/字段

问题描述

我正在尝试使用实体框架核心 3.0 建模和生成具有继承的数据库。

我正在遵循https://www.learnentityframeworkcore.com/inheritance/table-per-hierarchy中的指南

我的代码,我有 3 个类:父类是“源”,继承的子类是“出版物”和“馈线”

该指南告诉子类的所有字段都将在全局表中。但他们不是。

我的模型如下(一个父类,两个孩子)

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Legal.Models {
    public enum SourceType { Publication, Feeder }
    // An issuer can have one or more sources. Every source has a type among 3 types


    [Table("Source")]
    public class Source {
        // PK
        public int SourceId { get; set; }
        // Attributes
        public SourceType SourceType { get; set; }
        public string Description { get; set; }
    }


    [Table("Source")]
    public class Publication : Source {
        [MaxLength(13)]
        public string ISSN;
        [MaxLength(2048)]
        public string IssueTocUrl;

        // Generate FK in Issues
        // public List<Source> Sources { get; } = new List<Source>();
    }

    [Table("Source")]
    public class Feeder : Source {
        [MaxLength(2048)]
        public string FeederUrl;
    }

}

我使用以下命令行生成迁移

dotnet ef migrations add Version_0_0

它生成以下设计器代码(这似乎是正确的 - 检查源、馈送器和发布实体)

// <auto-generated />
using System;
using Legal.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;

namespace Legal.Migrations
{
    [DbContext(typeof(LegalDbContext))]
    [Migration("20191022181406_Version_0_0")]
    partial class Version_0_0
    {
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "3.0.0")
                .HasAnnotation("Relational:MaxIdentifierLength", 64);

            modelBuilder.Entity("Legal.Models.Issuer", b =>
                {
                    b.Property<int>("IssuerId")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("Description")
                        .HasColumnType("varchar(64)")
                        .HasMaxLength(64);

                    b.Property<string>("LandPageUrl")
                        .HasColumnType("longtext")
                        .HasMaxLength(2048);

                    b.HasKey("IssuerId");

                    b.ToTable("Issuer");
                });

            modelBuilder.Entity("Legal.Models.Source", b =>
                {
                    b.Property<int>("SourceId")
                        .ValueGeneratedOnAdd()
                        .HasColumnType("int");

                    b.Property<string>("Description")
                        .HasColumnType("longtext");

                    b.Property<string>("Discriminator")
                        .IsRequired()
                        .HasColumnType("longtext");

                    b.Property<int?>("IssuerId")
                        .HasColumnType("int");

                    b.Property<int>("SourceType")
                        .HasColumnType("int");

                    b.HasKey("SourceId");

                    b.HasIndex("IssuerId");

                    b.ToTable("Source");

                    b.HasDiscriminator<string>("Discriminator").HasValue("Source");
                });

            modelBuilder.Entity("Legal.Models.Feeder", b =>
                {
                    b.HasBaseType("Legal.Models.Source");

                    b.ToTable("Source");

                    b.HasDiscriminator().HasValue("Feeder");
                });

            modelBuilder.Entity("Legal.Models.Publication", b =>
                {
                    b.HasBaseType("Legal.Models.Source");

                    b.ToTable("Source");

                    b.HasDiscriminator().HasValue("Publication");
                });

            modelBuilder.Entity("Legal.Models.Source", b =>
                {
                    b.HasOne("Legal.Models.Issuer", null)
                        .WithMany("Sources")
                        .HasForeignKey("IssuerId");
                });
#pragma warning restore 612, 618
        }
    }
}

但是生成脚本只包含源表,没有任何子字段

using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Legal.Migrations
{
    public partial class Version_0_0 : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Issuer",
                columns: table => new
                {
                    IssuerId = table.Column<int>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    Description = table.Column<string>(maxLength: 64, nullable: true),
                    LandPageUrl = table.Column<string>(maxLength: 2048, nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Issuer", x => x.IssuerId);
                });

            migrationBuilder.CreateTable(
                name: "Source",
                columns: table => new
                {
                    SourceId = table.Column<int>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    SourceType = table.Column<int>(nullable: false),
                    Description = table.Column<string>(nullable: true),
                    Discriminator = table.Column<string>(nullable: false),
                    IssuerId = table.Column<int>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Source", x => x.SourceId);
                    table.ForeignKey(
                        name: "FK_Source_Issuer_IssuerId",
                        column: x => x.IssuerId,
                        principalTable: "Issuer",
                        principalColumn: "IssuerId",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateIndex(
                name: "IX_Source_IssuerId",
                table: "Source",
                column: "IssuerId");
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Source");

            migrationBuilder.DropTable(
                name: "Issuer");
        }
    }
}

注意:我已经尝试过 - 没有注释 - 使用数据注释配置 3 个表(源、出版物和 Feeder) - 使用数据注释仅配置 1 个表(源 - 当前示例) - 每个类使用 DbSet - 覆盖 OnModelCreating

        // Define the table based collections
        public DbSet<Issuer> Issuers { get; set; }
        // public DbSet<Source> Sources { get; set; }
        public DbSet<Publication> Publications { get; set; }
        public DbSet<Feeder> Feeders { get; set; }
        // Force creation of child Sources

        protected override void OnModelCreating(ModelBuilder modelBuilder) {
            modelBuilder.Entity<Publication>();
            modelBuilder.Entity<Feeder>();
        }

标签: .net-coreentity-framework-core

解决方案


我发现了我的(愚蠢的)错误。

我忘了声明 setter/getter。该过程仅生成带有 get/set 的字段。

这是正确的代码

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Legal.Models {
    public enum SourceType { Publication, Feeder }
    // An issuer can have one or more sources. Every source has a type among 3 types

    public abstract class Source {
        // PK
        public int SourceId { get; set; }
        // Attributes
        public SourceType SourceType { get; set; }
        [MaxLength(256)]
        public string Description { get; set; }
        [MaxLength(1024)]
        public string ServiceClass { get; set; }

        // Parent/Many to One relation shipp
        public int IssuerId { get; set; }
        public Issuer Issuer { get; set; }
    }


    public class Publication : Source {
        [MaxLength(13)]
        public string ISSN { get; set; }
        [MaxLength(2048)]
        public string IssueTocUrl { get; set; }

        // Generate FK in Issues
        public List<PublicationIssue> PublicationIssues { get; set; }
    }

    public class Feeder : Source {
        [MaxLength(2048)]
        public string FeederUrl { get; set; }
    }


}

推荐阅读