首页 > 解决方案 > EF Core 3.1 - 如何将已经组合的 PK 用于另一个组合的 PK?

问题描述

我目前正在学习使用 EF,我有以下关系:

警报有 1 到 n 次出现。每个出现可以有 0 到 n 个值(附加信息)。

public class Alert
{
    // PK
    public int AlertId { get; set; }

    // Attributes
    public int CurrentAlertLevel { get; set; }

    public DateTime TimeRaised { get; set; }
    public DateTime TimeLastRaised { get; set; }

// Some other attributes ommitted...        

    // Relations
    public ICollection<AlertOccurrence> Occurrences { get; set; }
}

public class AlertOccurrence
{
    // Relations which are part of the primary key
    public int AlertId { get; set; }

    // Attributes
    public int Ordinal { get; set; }

// some ommited attributes

    // Relations
    public ICollection<AlertDetailValue> AlertDetailValues { get; set; }
}

public class AlertDetailValue
{
    public int AlertDetailValueId { get; set; }
    public int Order { get; set; }
    public string Value { get; set; }
}

在 DB Context OnModelCreating 中,我正在为 AlertOccurence 设置组合 PK:

modelBuilder.Entity<AlertOccurrence>().HasKey(ao => new {ao.AlertId, ao.Ordinal});

虽然这似乎可行 - 我实际上想要存档的是相同的关系,而不需要将 AlertDetailValueId 作为 PK。EF 生成的表还包括 AlertOccurrenceAlertId 和 AlertOccurrenceOrdinal,这对我来说似乎是浪费空间。

所以我想做的是:拥有一个由 AlertDetailValue.Order 和 AlertOccurence 的(已经组合的)PK 而不是“人工”AlertDetailValueId 组成的 AlertDetailValue 的组合主键。这甚至可能吗?

我的部分问题可能是使用 fluent api 定义的 PK 不是数据类的一部分。所以可能要问的另一个问题是:有没有办法在实体类中使用 fluent api 中定义的键?

或者我是否需要在我的实体类 AlertDetailValue 中包含 AlertOccurrenceAlertId 和 AlertOccurrenceOrdinal - 但是我该如何链接它们呢?

正如我所说,我仍在努力了解 EF,所以虽然可能有更好的方法来做到这一点,但我对这种特殊的关系/组合(组合)PK 感兴趣,即使它可能是学术性的......任何帮助将不胜感激。

标签: entity-framework-core

解决方案


试图解释我尝试做什么以及我的问题是什么 - 并好好洗个澡 - 帮助我向谷歌提出不同的问题并更多地关注外键。不是我之前没有尝试过谷歌...我只是问了错误的问题..

所以我发现了这个: 将复合外键映射到复合主键,其中外键也是主键 (在尝试新方法时@atiyar也暗示缺少外键......)

我的新解决方案是更改 AlertDetailValue 以有意包含 Occurence PK 构建的部分:

    public class AlertDetailValue
    {
         // relations will be set up in fluent api in OnModelCreating of db context
        public int AlertOccurenceAlertId { get; set; }
        public int AlertOccurenceOrdinal { get; set; }

        public int Order { get; set; }
        public string Value { get; set; }
    }

然后告诉 EF 有一个组合的 PK 和一个组合的外键:

            modelBuilder.Entity<AlertDetailValue>().HasKey(adv => new { adv.AlertOccurenceAlertId, adv.AlertOccurenceOrdinal, adv.Order  });

            modelBuilder.Entity<AlertOccurrence>().HasMany<AlertDetailValue>(adv => adv.AlertDetailValues).WithOne()
                .HasForeignKey(adv => new {adv.AlertOccurenceAlertId, adv.AlertOccurenceOrdinal});

推荐阅读