我的 SQLite 数据库中有一个非标准外键情况,并且我无法控制架构来更改它。有一个父表具有子表的 FK,但 FK 所指向的字段不是子表的主键。我们有:
Parent Child
______ ______
Id Id
...fields ...fields
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 调用。似乎 EFCore 总是假设我希望它设置 ChildId,然后当我尝试将父对象添加到数据库时,这个问题就会爆发。
有什么方法可以获得我需要的行为吗?
听起来你的问题不是 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);