SQL 多个级联路径/ 无法首先确定类型实体框架代码之间关联的主体端



我的问题是我首先使用实体框架代码不断收到此错误"附加信息:引入外键约束'FK_dbo。Sets_dbo。表"集合"上的ExerciseStats_ExerciseStatId"可能会导致循环或多个级联路径。指定"删除时不执行任何操作"或"更新时不执行任何操作",或修改其他外键约束。

我的表格是:锻炼,锻炼统计,集合

public class Workout
{
[Key]
public int WorkoutId { get; set; }
public string UserId { get; set; }
[Display(Name = "Workout Name")]
public string Name { get; set; }
public DateTime? Date { get; set; }
public List<ExerciseStats> Exercises { get; set; }
public bool IsBaseWorkout { get; set; }
}
public class ExerciseStats
{
[Key]
public int ExerciseStatsId { get; set; }
[Required]
public int ExerciseId { get; set; }
[ForeignKey("ExerciseId")]
public Exercise Exercise { get; set; }
[Required]
public int WorkoutId { get; set; }
[ForeignKey("WorkoutId")]
public Workout Workout { get; set; }
public int DesiredSetId { get; set; }
[ForeignKey("DesiredSetId")]
public Set DesiredSet { get; set; }
public int DesiredSetCount { get; set; }
public List<Set> ActualSets { get; set; }

}
public class Set
{
[Key]
public int SetId { get; set; }
[Required]
public int ExerciseStatId { get; set; }
[ForeignKey("ExerciseStatId")]
public ExerciseStats ExerciseStat { get; set; }
public float? WeightInKg { get; set; }
public int? Reps { get; set; }
public float? Minutes { get; set; }
}

我已经查看代码一段时间了,似乎无法确定问题发生的位置。我尝试使用以下代码禁用级联删除:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ExerciseStats>()
.HasMany(p => p.ActualSets)
.WithRequired()
.HasForeignKey(c => c.ExerciseStatId)
.WillCascadeOnDelete(false);
}

这导致了此错误"附加信息:无法确定类型'GymDiaryCodeFirst.Models.Set'和'GymDiaryCodeFirst.Models.ExerciseStats'之间关联的主端。必须使用关系流畅 API 或数据注释显式配置此关联的主体端。

这对我来说没有意义,因为我已经在所需属性上使用了注释。

我试图实现的是一个集合表,当数据被删除时,它不会影响 exerciseStats 表或任何其他表。此外,exerciseStats 类包含一个名为 desiredSet 的属性,该属性也出现在 sets 表中。

整个星期天都在试图解决这个问题:( 感谢任何帮助。

我不知道以下内容是否会为您提供所需的设计,但肯定会解决您的实际问题:

将映射更改为:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ExerciseStats>()
.HasMany(p => p.ActualSets)
.WithRequired(x => x.ExerciseStat) //<-- Set the principal explicitly
.HasForeignKey(c => c.ExerciseStatId)
.WillCascadeOnDelete(false);
}

请注意,根据错误消息的要求,我们现在显式配置关系的主体端。

在您当前的代码中,我的猜测是,不带参数的调用会导致 EF 生成与 DB 不同的 FK 属性,因此,您编写的代码以避免多个级联路径,它既不会产生任何效果,也不会产生任何影响。

更新: 根据您的评论,正如我在我的评论中提到的,我认为这是您的设计存在的问题。我将尝试在此处提供更多详细信息:

如果您看到您的锻炼统计实体具有必需的集合。您可以通过不可为空的属性来判断这一点

public int DesiredSetId { get; set; }

同时,您的 Set 实体也需要一个 ExerciseStat:

public int ExerciseStatId { get; set; }

这将使得无法将一个锻炼添加到数据库,因为您需要一个集合实体来添加锻炼统计,反之亦然。

一种可能的解决方案是将其中一个必需属性设置为可选(使字段可为空(:

public int? DesiredSetId { get; set; }

这将允许您首先插入主体实体,然后使用生成的标识值创建从属实体。

希望这有帮助!

最新更新