2

我正在使用 EF Core 并以逐层表 (TPH) 方法实现继承。我发现,一旦我将层次结构对象添加到我的数据模型中,迁移就会为基表添加一个外键,并且似乎是后代类正在使用的副本。

关系是从Transaction(父母)到TransactionItem(孩子)。

对象层次结构:

  • TransactionItem(基类)
    • 附件
    • 查看
    • 信封
    • 存根

使用 Fluent API 定义关系TransactionTransactionItem使用TransactionItem.TransactionId字段作为外键:

modelBuilder.Entity<TransactionItem>(t =>
{
    t.ToTable("TransactionItem");
    t.HasKey(a => a.Id);
    t.Property(a => a.ConcurrencyStamp)
        .IsRequired()
        .IsConcurrencyToken();
    t.Property(a => a.Created)
        .IsRequired();
    t.HasOne(a => a.Transaction)
        .WithMany(a => a.TransactionItems)
        .HasForeignKey(a => a.TransactionId)
        .OnDelete(DeleteBehavior.Restrict);
    t.HasDiscriminator<string>("ItemType")
        .HasValue<Check>("Check")
        .HasValue<Stub>("Stub")
        .HasValue<Envelope>("Envelope")
        .HasValue<Attachment>("Attachment");
});

迁移 Up 方法是创建带有 TransactionIdTransactionId2列的基类表 (TPH),每个列都与同一个父表相关:

migrationBuilder.CreateTable(
name: "TransactionItem",
columns: table => new
{
    Id = table.Column<int>(nullable: false)
        .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
    ConcurrencyStamp = table.Column<string>(nullable: false),
    Created = table.Column<DateTimeOffset>(nullable: false),
    ItemType = table.Column<string>(nullable: false),
    PageName = table.Column<string>(nullable: true),
    Sequence = table.Column<int>(nullable: false),
    TransactionId = table.Column<int>(nullable: false),
    TransactionId2 = table.Column<int>(nullable: true),
    CheckType = table.Column<string>(nullable: true),
    Micr = table.Column<string>(nullable: true),
    MicrValid = table.Column<bool>(nullable: true),
    OcrId = table.Column<string>(nullable: true)
},
constraints: table =>
{
    table.PrimaryKey("PK_TransactionItem", x => x.Id);
    table.ForeignKey(
        name: "FK_TransactionItem_Transaction_TransactionId",
        column: x => x.TransactionId,
        principalTable: "Transaction",
        principalColumn: "Id",
        onDelete: ReferentialAction.Restrict);
    table.ForeignKey(
        name: "FK_TransactionItem_Transaction_TransactionId2",
        column: x => x.TransactionId2,
        principalTable: "Transaction",
        principalColumn: "Id",
        onDelete: ReferentialAction.Restrict);
});

当我查看 ModelSnapshot.cs 代码时,我看到以下关系特定于继承模型中的对象,该关系使用该列为派生类实体建立外键TransactionId2

modelBuilder.Entity("SampleProject.Data.DataModels.TransactionItem", b =>
    {
        b.HasOne("SampleProject.Data.DataModels.Transaction", "Transaction")
            .WithMany("TransactionItems")
            .HasForeignKey("TransactionId");
    });

modelBuilder.Entity("SampleProject.Data.DataModels.Attachment", b =>
    {
        b.HasOne("SampleProject.Data.DataModels.Transaction")
            .WithMany("Attachments")
            .HasForeignKey("TransactionId2");
    });

modelBuilder.Entity("SampleProject.Data.DataModels.Check", b =>
    {
        b.HasOne("SampleProject.Data.DataModels.Transaction")
            .WithMany("Checks")
            .HasForeignKey("TransactionId2");
    });

modelBuilder.Entity("SampleProject.Data.DataModels.Envelope", b =>
    {
        b.HasOne("SampleProject.Data.DataModels.Transaction")
            .WithMany("Envelopes")
            .HasForeignKey("TransactionId2");
    });

modelBuilder.Entity("SampleProject.Data.DataModels.Stub", b =>
    {
        b.HasOne("SampleProject.Data.DataModels.Transaction")
            .WithMany("Stubs")
            .HasForeignKey("TransactionId2");
    });

我显然错过了一些东西,但无法弄清楚它是什么。我希望能够使用带有 TPH 方法的继承层次结构和从基类表 ( TransactionItem) 到父表 ( ) 的单个外键字段Transaction。感谢您提供的任何帮助。

谢谢!

4

1 回答 1

1

正如 Ivan Stoev 所指出的,我通过让父对象(在这种情况下)为我的派生类类型列表Transaction实现只读便利属性来创建这个问题。

因为Transaction声明的属性如下所示,ef 迁移正在为它们创建新的关系/外键。

public List<Check> Checks
{
    get
    {
        return this.TransactionItems?.OfType<Check>().ToList();
    }
}

我已经将这些实现为方法,以免与 ef 的约定冲突。

非常感谢 Ivan Stoev 促成了这一发现!

于 2017-09-15T17:48:20.637 回答