实体有两个属性,它们都以一对多的关系引用相同的实体类型

本文关键字:实体 一对多 关系 引用 类型 属性 两个 | 更新日期: 2023-09-27 18:15:13

这似乎是最常见的关系,但由于某种原因,我无法让代码优先的EF工作。当我运行下面的代码时,我得到以下错误:

*{"在表' records '上引入外键约束'Recording_RecordingLocation'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他外键约束。'r'n无法创建约束。请参阅前面的错误。"}*

我已经研究了SO和其他地方,但还没能弄清楚。我一定是小中风了,如果这是重复的话,我道歉。我不认为这是因为我发现的所有其他参考问题都是针对多对多关系的……多对一。

我的场景很简单…

我有一个实体(录音),它有两个必需的属性RecordingLocation和EditingLocation,这两个属性都是相同类型的WorkLocation。每个录音都有一个RecordingLocation和一个EditingLocation (不是多对多)。我也有必要的导航属性。

每个工作位置都是独立的,并且与记录没有内在的联系——它只是一个物理位置,在那里记录的一些工作发生了。因此,当我删除一个记录时,我不想删除相关的WorkLocations。

public class Recording
{
    [Key]
    public virtual int Id { get; set; }
    //... other properties not shown here
    public virtual int RecordingLocationId { get; set; }
    public virtual WorkLocation RecordingLocation { get; set; }
    public virtual int EditingLocationId { get; set; }
    public virtual WorkLocation EditingLocation { get; set; }
{

public class WorkLocation
{
    [Key]
    public virtual int Id { get; set; }
    public virtual WorkLocationType Type { get; set; }
    public virtual string Description { get; set; }
    public virtual LogicalStatus Status { get; set; }
}
// I'll use this on the front-end to filter a selection list
// but don't necessarily assume a Work Location is bound to only items of this type
public enum WorkLocationType
{
    RecordingLocation,
    EditingLocation,
    MasteringLocation
}

我错过了什么让这个工作?

实体有两个属性,它们都以一对多的关系引用相同的实体类型

导航属性RecordingLocationEditingLocation是必需的,因为相应的外键属性不可为空。按照惯例,EF假设对于一个必需的一对多关系,级联删除是活动的,如果有多个这样的关系引用同一个表,就会产生问题——因此会出现异常。

你必须禁用级联删除(你的业务逻辑似乎也需要它),这只可能在Fluent API:

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Recording>()
            .HasRequired(r => r.RecordingLocation)
            .WithMany()
            .HasForeignKey(f => f.RecordingLocationId)
            .WillCascadeOnDelete(false);
        modelBuilder.Entity<Recording>()
            .HasRequired(r => r.EditingLocation)
            .WithMany()
            .HasForeignKey(f => f.EditingLocationId)
            .WillCascadeOnDelete(false);
    }
}