【问题标题】:'Introducing FOREIGN KEY constraint' due to cascading deletes由于级联删除,“引入 FOREIGN KEY 约束”
【发布时间】:2016-11-04 12:25:18
【问题描述】:

引入 FOREIGN KEY 约束 'FK_dbo.CurrentAnimal_dbo.AnimalClass_SelectedAnimalClass' 在桌子上 “CurrentAnimal”可能会导致循环或多个级联路径。指定开 DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

我已经研究了这个问题,并从下面的问题中发现了最多的问题。

Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?

但是我无法从中找到解决方案,因为我的实体关系与提问者有很大不同。

想象一下,我的网站用于浏览动物园中的许多不同动物,您首先选择 AnimalClass(比如鸟),然后选择 Species(可能是鹰),最后选择所有鹰中的特定动物来过滤搜索在动物园里(让我们称他为鹰杰克)。

为了做到这一点,我有 3 个模型(AnimalClass

动物类

用户请求查看。

AnimalClass.cs

  public class AnimalClass
  {
    public int Id { get; set; }

    [Required]
    public string AnimalClassName { get; set; }

    //Navigation property
    public virtual ICollection<Species> Species { get; set; }
  }

物种.cs

  public class Species
  {
    public int Id { get; set; }

    [Required]
    public string SpeciesName { get; set; }

    [Required]
    public int SpeciesAnimalClassId { get; set; }//Foreign Key to the parent Animal Class

    [ForeignKey("SpeciesAnimalClassId")]
    public virtual AnimalClass SpeciesAnimalClass { get; set; }

    //Navigation property
    public virtual ICollection<Animal> Animals { get; set; }
  }

Animal.cs

  public class Animal
  {
    public int Id { get; set; }

    [Required]
    public string AnimalName { get; set; }

    [Required]
    public int AnimalsSpeciesId { get; set; }//Foreign Key to the parent Animal Species

    [ForeignKey("AnimalsSpeciesId")]
    public virtual Species AnimalsSpecies { get; set; }
  }

CurrentAnimal.cs

  public class CurrentAnimal
  {
    [Key, ForeignKey("User")]//Acts as both the key to the table, and foreign key to users
    public string UserId { get; set; }

    [Required]
    public int SelectedAnimalClass { get; set; }

    [Required]
    public int SelectedSpecies { get; set; }

    [Required]
    public int SelectedAnimal { get; set; }

    [ForeignKey("SelectedAnimalClass")]
    public virtual AnimalClass AnimalClass { get; set; }

    [ForeignKey("SelectedSpecies")]
    public virtual Species Species { get; set; }

    [ForeignKey("SelectedAnimal")]
    public virtual Animal Animal { get; set; }

    public virtual ApplicationUser User { get; set; }
  }

我知道问题在于我有多个导致异常的级联删除,我根本无法确定需要删除哪些必需的注释或我需要使用 Fluent API 禁用级联删除的实体。

我尝试删除 CurrentAnimal.cs 中的必需注释,然后在我的 DbContext 中使用 Fluent API 来禁用对 AnimalClass、Species 和 Animal 的级联删除,但这并没有改变或删除错误。

这是我在删除 CurrentAnimal.cs 中的必需标签后尝试的

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<CurrentAnimal>()
      .HasRequired(s => s.AnimalClass)
      .WithMany()
      .WillCascadeOnDelete(false);

  modelBuilder.Entity<CurrentAnimal>()
      .HasRequired(s => s.Species)
      .WithMany()
      .WillCascadeOnDelete(false);

  modelBuilder.Entity<CurrentAnimal>()
      .HasRequired(s => s.Animal)
      .WithMany()
      .WillCascadeOnDelete(false);

}

【问题讨论】:

  • 为什么你的 CurrentAnimal 实体(也是奇怪的名字)有“物种”和“动物类”的字段?这些都是通过引用“动物”已经可以获得的信息,并且可能导致数据库中的不一致。
  • ...你是完全正确的。所以我什至不需要存储其他两个类,因为我可以只引用动物物种然后引用物种动物类?这样能解决问题吗?

标签: c# entity-framework foreign-key-relationship cascading-deletes ef-fluent-api


【解决方案1】:

多个级联路径是由于删除一个 Species 时,有两条路径可能导致删除 CurrentAnimal:

Species -> Animal -> CurrentAnimal
Species -> CurrentAnimal

AnimalClass 也是如此。

如果您绝对必须拥有这些冗余引用,则需要使其中一些成为没有级联的外键。理论上它应该仍然有效。

然而,更好的解决方案是不要有多余的引用,因为这会导致数据不一致。例如,您可能有一个具有 SelectedSpecies 的 CurrentAnimal,它与 SelectedAnimal 的物种不同。

【讨论】:

  • 是的,这似乎是问题所在。我可以保留它们,但存储冗余信息没有任何意义。我将尝试删除它们。
  • 这修复了它。谢谢。
猜你喜欢
  • 2015-04-29
  • 2014-03-20
  • 2019-10-05
  • 2019-11-01
  • 2018-08-08
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2011-05-08
相关资源
最近更新 更多