我可以关闭 EF Core 外键映射吗?

问题描述 投票:0回答:2

我的 SQLite 数据库中有一个非标准外键情况,并且我无法控制架构来更改它。有一个父表具有子表的 FK,但 FK 所指向的列不是子表的主键。

我们有:

Parent       Child
______       ______
Id           Id
...columns   ...columns
ExternalId
ChildId  --> ExternalId

这在 EF POCO 中建模为:

class Parent
{
    public int Id { get; set; }
    public int ExternalId { get; set; }
    public int ChildId { get; set; }
    public Child Child { get; set; }
}

class Child
{
    public int Id { get; set; }
    public int ExternalId { get; set; }
    public int ChildId { get; set; }
}

我的应用程序从 Web API 请求获取父/子数据,这些实体具有来自远程服务器的

ExternalId
。我们将它们序列化到本地 SQLite 数据库,其中
Parent.Id
Child.Id
是自动递增的主键,我们想要
Parent.ChildId == Child.ExternalId
。是的,我知道这不是好的范式,但我无法改变它。

Parent.ChildId
由外部服务提供,我不希望在 EF 中设置它,但无论我做什么,当我尝试将父对象添加到数据上下文时,EF 都会将
Parent.ChildId
设置为某些自动递增值,而不是不管它。

即使我删除所有

[ForeignKey]
属性也是如此。

我找不到任何可以正确处理 ChildId FK 的属性组合或流畅的 API 调用。似乎 EF Core 总是假设我希望它设置 ChildId,然后当我尝试将父对象添加到数据库时,就会发生这种情况。

有什么方法可以获得我需要的行为吗?

c# sqlite entity-framework-core
2个回答
0
投票

听起来你的问题不是 FK,而是事实上 FK 指向这个ExternalId,而你分配了一个新的、任意的 PK 列。 (Id) 外键通常指向 PK。

最简单的事情就是接受这些表将由外部系统“拥有”,其中外部 ID 是 PK。如果不将其用于关系,或者让某些关系使用 Id,而其他关系则依赖ExternalId,我不明白通过添加任意自动增量列来充当 PK 有何好处。

或者,您可以显式设置关系以使用ExternalId作为关系的主体:

modelBuilder.Entity<Parent>()
    .HasOne(x => x.Child)
    .WithOne()
    .HasForeignKey<Parent>(x => x.ChildId)
    .HasPrincipalKey<Child>(x => x.ExternalId);

0
投票

您可以使用 Fluent API 来配置关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Child>()
     .HasIndex(c => c.ExternalId)
     .IsUnique(); // ExternalId should be a PK or unique index

    modelBuilder.Entity<Parent>()
      .HasOne(p => p.Child)
      .WithMany()
      .HasForeignKey(nameof(Parent.ChildId))
      .HasPrincipalKey(nameof(Child.ExternalId));
}

这会创建以下

Parents
表:

CREATE TABLE "Parents" (
    "Id" INTEGER NOT NULL CONSTRAINT "PK_Parents" PRIMARY KEY AUTOINCREMENT,
    "ExternalId" INTEGER NOT NULL,
    "ChildId" INTEGER NOT NULL,
    CONSTRAINT "FK_Parents_Children_ChildId" FOREIGN KEY ("ChildId") REFERENCES "Children" ("ExternalId") ON DELETE CASCADE
);

附注

我认为你的术语有点颠倒,如果

Parent
引用
Child
那么它实际上是一个子表。

© www.soinside.com 2019 - 2024. All rights reserved.