EF Core 流畅 API 中的“幽灵”影子键

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

我有这个设置(粗略地说,我已经编辑掉了不相关的代码以提高可读性)。

public class LevelSection
{
    public Guid Id { get; set; }
    public Guid UserDataId { get; set; }
}

然后

public class UserData
{
    public Guid Id { get; set; }
    public LevelSection SkillsSection { get; set; }
    public LevelSection LanguageSection { get; set; }
    public IList<LevelSection> CustomLevelSections { get; set; }
}

我在 EF core 中使用代码优先的方法。我希望这两个表“连接”,以便

UserData
表只有其
Id
,然后拥有
LevelSection
表,该表将
UserDataId
作为外键。

我在

OnModelCreating
中尝试了许多流畅的 api 配置,其中许多都给了我不同的错误(主要是沿着 - 这两者之间已经定义了关系)。然而,我设法找到了一些看起来像我想要实现的目标:

modelBuilder.Entity<UserData>()
      .HasMany(a => a.CustomLevelSections)
      .WithOne()
      .HasForeignKey(c => c.UserDataId)
      .OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<UserData>()
      .HasOne(a => a.SkillsSection)
      .WithOne()
      .HasForeignKey<LevelSection>(e => e.UserDataId)
      .OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<UserData>()
      .HasOne(a => a.LanguageSection)
      .WithOne()
      .HasForeignKey<LevelSection>(e => e.UserDataId)
      .OnDelete(DeleteBehavior.Cascade);

但现在我在 UserDataId 上获得了影子属性 -

The foreign key property 'LevelSection.UserDataId1' was created in shadow state because a conflicting property with the simple name 'UserDataId' exists in the entity type, but is either not mapped, is already used for another relationship, or is incompatible with the associated primary key type. See https://aka.ms/efcore-relationships for information on mapping relationships in EF Core.

上面是 UserData 中所有出现的

LevelSection
对象,所以我没想到会出现这种情况。并且似乎无法弄清楚这是从哪里来的。也非常欢迎具有相同结果的替代方法(或此时的任何其他想法)。

c# entity-framework-core ef-code-first ef-fluent-api
1个回答
0
投票

正如评论中提到的,FK只能服务于一种关系。您正在链接表之间的 2 个一对一关系和一个一对多关系。不管你怎么削减,它都是 3x FK。

public class UserData
{
    public Guid Id { get; set; }
    [ForeignKey(nameof(SkillSection)]
    public Guid SkillLevelSectionId { get; set; }
    public LevelSection SkillsSection { get; set; }
    [ForeignKey(nameof(LanguageSection)]
    public Guid LanguageLevelSectionId { get; set; }
    public LevelSection LanguageSection { get; set; }
    public IList<LevelSection> CustomLevelSections { get; set; }
}

这些一对一的 FK 可以存在于 UserData 或链接表上,但在 UserData 上可能更有意义。在 LevelData 表上,它将类似于 UserDataIdIAmALanguageSectionFor 和 UserDataIdIAmASkillSectionFor 来区分它们,而不是 UserDataId1 和 UserDataId2 以及 UserDataId。

另一种方法是将技能和语言部分表示为单独的表格。尝试将仅仅“相似”的数据放入单个表中可能会适得其反。在现代数据系统中,存储空间很便宜,因为索引/读取分布在具有唯一索引的 3 个表中的 200k 条记录比尝试从单个表中读取 200k 条记录更快,而您必须做出妥协,这很少是一个好主意。

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