派生类型首先使用 TPH 在代码中生成自己的 ForeignKey 字段
Derived types generating their own ForeignKey field in code first using TPH
我正在使用 EF Core 并以 table-per-hierarchy (TPH) 方法实现继承。我发现一旦我将层次结构 objects 添加到我的数据模型中,迁移就会为基础 table 添加一个外键,并且似乎是后代 classes 的副本正在使用。
关系是从 Transaction
(parent) 到 TransactionItem
(child)。
Object 层级:
- TransactionItem(基础 class)
- 附件
- 检查
- 信封
- 存根
使用Fluent API定义Transaction
和TransactionItem
之间的关系,使用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");
});
向上迁移方法正在创建具有 TransactionId
和 TransactionId2
列的基础 class table (TPH),每个列都与相同的 parent 相关table:
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 代码时,我看到以下关系特定于继承模型中的 objects 使用 [= 为派生的 class 实体建立外键19=]列。
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 方法和从基础 class table (TransactionItem
) 到 parent (Transaction
).感谢您提供的任何帮助。
谢谢!
正如 Ivan Stoev 所指出的,我通过让父对象(在本例中为 Transaction
)为我派生的 class 类型。
因为 Transaction
声明了如下属性,ef 迁移正在为它们创建新的 relationships/foreign 键。
public List<Check> Checks
{
get
{
return this.TransactionItems?.OfType<Check>().ToList();
}
}
我已经将这些实现为方法,以免与 ef 的约定冲突。
非常感谢 Ivan Stoev 促使这一发现!
我正在使用 EF Core 并以 table-per-hierarchy (TPH) 方法实现继承。我发现一旦我将层次结构 objects 添加到我的数据模型中,迁移就会为基础 table 添加一个外键,并且似乎是后代 classes 的副本正在使用。
关系是从 Transaction
(parent) 到 TransactionItem
(child)。
Object 层级:
- TransactionItem(基础 class)
- 附件
- 检查
- 信封
- 存根
使用Fluent API定义Transaction
和TransactionItem
之间的关系,使用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");
});
向上迁移方法正在创建具有 TransactionId
和 TransactionId2
列的基础 class table (TPH),每个列都与相同的 parent 相关table:
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 代码时,我看到以下关系特定于继承模型中的 objects 使用 [= 为派生的 class 实体建立外键19=]列。
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 方法和从基础 class table (TransactionItem
) 到 parent (Transaction
).感谢您提供的任何帮助。
谢谢!
正如 Ivan Stoev 所指出的,我通过让父对象(在本例中为 Transaction
)为我派生的 class 类型。
因为 Transaction
声明了如下属性,ef 迁移正在为它们创建新的 relationships/foreign 键。
public List<Check> Checks
{
get
{
return this.TransactionItems?.OfType<Check>().ToList();
}
}
我已经将这些实现为方法,以免与 ef 的约定冲突。
非常感谢 Ivan Stoev 促使这一发现!