.net-core - 迁移中不生成继承的子表/字段
问题描述
我正在尝试使用实体框架核心 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>();
}
解决方案
我发现了我的(愚蠢的)错误。
我忘了声明 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; }
}
}
推荐阅读
- blazor - Blazor CascadingParameter - MainLayout.razor 和 NavMenu.razor 之间
- emacs - Emacs:启用 CUA 模式时如何重新定义 Ctrl-Enter?
- reactjs - NextJS 在 Firebase Functions Deploy 上引发错误
- javascript - 尝试提供新的 html 文件后收到“发送到客户端后无法设置标题”错误
- c++ - Emscripten:如何为 C++ 数组类型定义 webidl
- java - Java/Kotlin Android 应用的通用应用状态架构?
- javascript - 当我使用 ip:port 时 getUserMedia 未定义
- python - 如何使用指定的 ca 文件通过 ssl 执行 get 请求
- kotlin - 如何在 Kotlin 中实现域实体?
- ios - 使用虚拟对象捕获 ARSCNView - iOS