entity-framework-core - 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 感兴趣,即使它可能是学术性的......任何帮助将不胜感激。
解决方案
试图解释我尝试做什么以及我的问题是什么 - 并好好洗个澡 - 帮助我向谷歌提出不同的问题并更多地关注外键。不是我之前没有尝试过谷歌...我只是问了错误的问题..
所以我发现了这个: 将复合外键映射到复合主键,其中外键也是主键 (在尝试新方法时@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});
推荐阅读
- maven - 哪个dependencyManagement 正在设置我的依赖版本?
- database - 每次我想在终端上运行`mongo`时如何跳过运行`mongod`?
- ruby-on-rails - Mac cocoapod 和 gem 命令抛出错误,不允许操作 - getcwd (Errno::EPERM)
- javascript - 如何合并/加入两个组件父/子状态反应
- regex - 如何删除 &fbclid 之后的文本
- spring-boot - 为什么部署的 spring boot jar 与开发机相比在日志中显示不同的不必要消息?
- gem5 - RISCV-V 在 Gem5 上的实现
- python - 通过用 Python 编写的 timetrigger azure 函数在 azure blob 中上传数据
- python - 使用 Tensorflow 1.X 的 Horovod 局部梯度聚合
- gerrit - Gerrit 樱桃采摘