首页 > 解决方案 > FOREIGN KEY 约束 可能导致循环或多路径

问题描述

我已经阅读了大量看似与我的问题相似的文章,但还没有找到我理想的解决方案。

我的具体错误说:

在表 'Scores' 上引入 FOREIGN KEY 约束 'FK_Scores_Tees_TeeId' 可能会导致循环或多个级联路径。

因此,这里有问题的表格如下所示:

    {
        [Key]
        public Guid ScoreId { get; set; }
        public int Strokes { get; set; }
        public Guid PersonId { get; set; }
        public Guid CourseId { get; set; }
        public Guid TeeId { get; set; }


        [ForeignKey("PersonId")]
        public virtual Person Person { get; set; }
        [ForeignKey("CourseId")]
        public virtual Course Course { get; set; }
        [ForeignKey("TeeId")]
        public virtual Tee Tee { get; set; }
    } 

现在,该表引用了 Tees 表,如下所示:

    public class Tee
    {
        [Key]
        public Guid TeeId { get; set; }
        public string Name { get; set; }
        public int Par { get; set; }
        public int Yards { get; set; }
        public float Rating { get; set; }
        public int Slope { get; set; }
        public Guid CourseId { get; set; }

        [ForeignKey("CourseId")]
        public virtual Course Course { get; set; }
    }

我阅读了有关在 Scores 表中使 TeeId 可以为空的信息。我做到了,并且能够成功构建运行我的迁移......但是我确实需要这个字段。如果该 id 为空/null,那么我没有关于该特定分数记录的足够信息。

标签: entity-framework-core

解决方案


两者TeeScore需要参考Course. 当您删除一个引用的Course时,EF 将要删除关联的Teeand Score。删除时Tee,EF 将再次要删除关联的Score. 这就是“多级联路径”问题。

这个错误暴露了设计的问题;这两个引用Course可以是不同的值,这在所使用的上下文中没有意义(分数是针对一门课程而引用另一门课程的“发球台”?)。你应该重构你的设计。

高尔夫球中的发球台通常是颜色(蓝色、白色、金色、红色)或名称(女士、后卫/冠军、老年人等)的一小部分价值。解决您的设计问题的一种方法是在表格中规范化这些名称和/或颜色值Tee,然后有一个CourseTee表格来定义Course's tee 的属性。这将通过使用由 FK 的 toCourse和组成的复合键作为主键或候选键(在 EF 中称为备用键)来完成Tee。然后,您可以在该实体中定义课程 T 恤的属性:

public class CourseTee
{
    [Key]
    public Guid CourseId { get; set; }
    public Course Course { get; set; ]
    [Key]
    public Guid TeeId { get; set; }
    public Tee Tee { get; set; }

    public int Par { get; set; }
    // additional course-tee specific properties
    ...
}

public class Score  // as a golfer, change this to `Round`
{
    [Key]
    public Guid ScoreId { get; set; }  // RoundId :D
    public Person Player { get; set; }
    public CourseTee CourseTee { get; set; }
    public int Strokes { get; set; }
    ...
}

public class Tee
{
    public Guid TeeId { get; set; }
    public string Color { get; set }
    public string Name { get; set; }
}

NowCourse只在 aScore的对象图中定义一次。获得Course给定Score的只是一个额外的跳跃:score.CourseTee.Course


推荐阅读