entity-framework-core - EF Core - 与相同依赖实体类型的附加导航属性的一对多关系
问题描述
我在 EF Core 中配置我的关系时遇到问题。我受到以下例外的欢迎 -
指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束
我已经为这篇文章删减了实体,但是这两个实体都有自己的表格。
public class ApplicationSetupTest
{
public Guid Id { get; set; }
public Guid SchemeId { get; set; }
public string Description { get; set; }
public Guid LatestVersionId { get; set; }
public ApplicationSetupVersionTest LatestVersion { get; set; }
public ICollection<ApplicationSetupVersionTest> VersionHistory { get; set; }
}
public class ApplicationSetupVersionTest
{
public Guid Id { get; set; }
public Guid SetupId { get; set; }
public string Data { get; set; }
public string AuditComment { get; set; }
public Guid PreviousVersionId { get; set; }
}
该类有效地使用作为导航属性键的ApplicationSetupTest
静态数据定义。LatestVersionId
LatestVersion
该类ApplicationSetupVersionTest
是版本化/审计的数据。这些中的每一个都有一个SetupId
将其链接回ApplicationSetupTest
所指的对象。
我VersionHistory
纯粹为这篇文章添加了该属性,以证明ApplicationSetupVersionTest
每个ApplicationSetupTest
. 我没有添加一个ApplicationSetupTest
,ApplicationSetupVersionTest
因为这不是我期望需要的。
我的配置ApplicationSetupTest
如下:
public class ApplicationSetupEntityConfiguration : IEntityTypeConfiguration<ApplicationSetupTest>
{
public void Configure(EntityTypeBuilder<ApplicationSetupTest> builder)
{
builder.Property(t => t.SchemeId).IsRequired();
builder.Property(t => t.Description).IsRequired();
builder.Property(t => t.LatestVersionId).IsRequired();
builder.HasMany(t => t.VersionHistory)
.WithOne()
.HasForeignKey(t => t.SetupId)
.IsRequired();
builder.HasOne(t => t.LatestVersion)
.WithOne()
.HasForeignKey<ApplicationSetupTest>(t => t.LatestVersionId)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
builder.HasOne<Scheme>()
.WithMany()
.HasForeignKey(t => t.SchemeId)
.IsRequired();
}
}
- HasMany
> WithOne
onVersionHistory
用于定义当我删除设置时,我应该删除所有版本实体。
因此,我认为第二种配置是需要更改的区域。是在 Google 搜索之后添加的OnDelete(NoAction)
,我还尝试删除IsRequired()
以及使null 可以为LatestVersionId
空。
我正在寻找配置第二个关系,以便LatestVersion
可以在查询中包含该属性。
关于如何配置这种关系的任何想法?还是我在做一些你不推荐的事情?
解决方案
(为了简单起见,我将模型称为Setup
和Version
)。
使用您的一对多配置 -
builder.HasMany(t => t.VersionHistory)
.WithOne()
.HasForeignKey(t => t.SetupId)
.IsRequired();
您已声明Setup
为主端和Version
从属端,这是正确的。
但是你有一个LatestVersionId
外键Setup
,引用Version
和配置一对一关系 -
builder.HasOne(t => t.LatestVersion)
.WithOne()
.HasForeignKey<ApplicationSetupTest>(t => t.LatestVersionId)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
试图配置Setup
为从属端和Version
主端。我相信你可以看到矛盾。
使用以下简化模型 -
public class Setup
{
public Guid Id { get; set; }
public string Description { get; set; }
public Version LatestVersion { get; set; }
public ICollection<Version> VersionHistory { get; set; }
}
public class Version
{
public Guid Id { get; set; }
public string Data { get; set; }
// not nullable - every Version must belong to a Setup
public Guid SetupIdHistory { get; set; }
// nullable - not every Version is a latest version
public Guid? SetupIdLatest { get; set; }
}
您可以正确配置它们以将您的关系表示为 -
public void Configure(EntityTypeBuilder<Setup> builder)
{
builder.HasMany(p => p.VersionHistory)
.WithOne()
.HasForeignKey(p => p.SetupIdHistory)
.OnDelete(DeleteBehavior.Cascade) // not required, cascading is default
.IsRequired();
builder.HasOne(p => p.LatestVersion)
.WithOne()
.HasForeignKey<Version>(p => p.SetupIdLatest)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired(false);
}
如果您选择不为一对多关系使用外键,EF 将为您创建一个可为空的外键,并使用影子属性在模型级别管理该关系。但是对于一对一的关系,你必须定义一个外键。
public class Version
{
public Guid Id { get; set; }
public string Data { get; set; }
// nullable - not every Version is a latest version
public Guid? SetupId { get; set; }
}
public void Configure(EntityTypeBuilder<Setup> builder)
{
builder.HasMany(p => p.VersionHistory)
.WithOne()
.OnDelete(DeleteBehavior.Cascade)
.IsRequired(); // this will have no effect, the FK will be nullable
builder.HasOne(p => p.LatestVersion)
.WithOne()
.HasForeignKey<Model.Version>(p => p.SetupId)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired(false);
}
推荐阅读
- python - 在 Python 中迭代浮点列表
- c# - 如何防止 string.Replace() 方法替换相似但不需要的数据?
- reactjs - 根据 Firebase 状态导航到另一个屏幕
- ffmpeg - 如何修复 ffmpeg 未找到 | 不和谐.py
- javascript - 创建组件后丢失动画
- python - 如何准确获取图像中形状的轮廓?
- wordpress - 下拉菜单仅在引导程序 4 上的 WordPress 中有效一次
- python-3.x - Sqlite3 dbase 表永久锁定写入
- javascript - 在全前端 React 应用程序中将本地状态数据保存在 localStorage 中通常是否安全?
- python - 如何查看数据框两列之间的最大值以及一列中有多少值大于另一列?