EF核心-具有相同依赖实体类型的附加导航属性的一对多关系



我在EF Core中配置关系时遇到问题。我遇到了以下例外-

指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREING 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有效地定义静态数据,CCD_2是导航属性LatestVersion的关键。

ApplicationSetupVersionTest类是经过版本控制/审核的数据。其中每一个都有一个SetupId,将其链接回所引用的ApplicationSetupTest

我添加VersionHistory属性纯粹是为了说明在每个ApplicationSetupTest上可能有多个ApplicationSetupVersionTest。我还没有在ApplicationSetupVersionTest上添加ApplicationSetupTest,因为这不是我想要的。

我对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->VersionHistory上的WithOne定义了当我删除设置时,我应该删除所有版本实体。

因此,我认为第二种配置是需要改变的领域。OnDelete(NoAction)是在谷歌搜索后添加的,我还尝试删除IsRequired(),并使LatestVersionId可以为null。

我希望配置第二个关系,以便LatestVersion属性可以包含在查询中。

关于如何配置这样的关系,有什么想法吗?还是我在做一些你不会推荐的事情?

(为了简单起见,我将把模型称为SetupVersion)。

使用您的一对多配置-

builder.HasMany(t => t.VersionHistory)
.WithOne()
.HasForeignKey(t => t.SetupId)
.IsRequired();

您已经声明Setup为主端,Version为从属端,这是正确的。

但是,在Setup中有一个LatestVersionId外键,引用Version,并配置一对一关系-

builder.HasOne(t => t.LatestVersion)
.WithOne()
.HasForeignKey<ApplicationSetupTest>(t => t.LatestVersionId)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();

尝试将CCD_ 27配置为从属端。我相信你能看出其中的矛盾。

采用以下简化模型-

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将为您创建一个可为null的外键,并使用shadow属性在模型级别管理关系。但是对于一对一关系,必须定义外键。

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);
}

相关内容

  • 没有找到相关文章

最新更新