c# - SQL多重级联路径/无法先确定类型 Entity Framework 代码之间关联的主体端

标签 c# sql entity-framework ef-fluent-api

我的问题是,我总是首先使用实体​​框架代码收到此错误“附加信息:在表‘集合’上引入外键约束‘FK_dbo.Sets_dbo.ExerciseStats_ExerciseStatId’可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。”

我的表格是:workouts、exerciseStats、sets

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 的属性,它也出现在集合表中。

整个星期天都在想办法解决这个问题:( 感谢您的帮助。

最佳答案

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

将您的映射更改为:

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 属性,因此,您为避免多个级联路径而编写的代码既没有任何效果也没有有什么不同。

UPDATE: As per your comment, and as I mentioned in mine, I think this is a problem with your design. I'll try to provide some more details here:

如果您看到您的 ExerciseStat 实体有一个必需的集合。您可以通过不可为 null 的属性来判断这一点

public int DesiredSetId { get; set; }

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

public int ExerciseStatId { get; set; }

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

一种可能的解决方案是将您的必需属性之一设为可选(使该字段可为空):

public int? DesiredSetId { get; set; }

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

希望这对您有所帮助!

关于c# - SQL多重级联路径/无法先确定类型 Entity Framework 代码之间关联的主体端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45270445/

相关文章:

c# - 找不到 Entity Framework 4 注释

c# - 在 C# 中使用原始套接字

sql - oracle sql - 查询以查找特殊字符

c# - EF Core 中是否存在等效于 Database.CompatibleWithModel(bool)

sql - 如果我更改 SQL Server 中现有列字段大小的字符大小,有什么缺点?

mysql - 如何使用 WorkBench 将 MySQL 数据库表逐一逆向工程到 ERD 上

entity-framework - EF Core 2.0枚举存储为字符串

c# - 具有 MVVM 模式的 WPF 递归 TreeView

c# - NUnit - 默认重试异常

c# - LINQ 表达式树是专有树吗?