Dot-Net

引入 FOREIGN KEY 約束可能會導致循環或多個級 聯路徑 - 為什麼?

  • June 15, 2013

我已經為此苦苦掙扎了一段時間,無法完全弄清楚發生了什麼。我有一個卡片實體,其中包含邊(通常是 2 個)-卡片和邊都有一個階段。我正在使用 EF Codefirst 遷移,遷移失敗並出現以下錯誤:

在表“Sides”上引入 FOREIGN KEY 約束“FK_dbo.Sides_dbo.Cards_CardId”可能會導致循環或多個級​​聯路徑。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 約束。

這是我的Card實體:

public class Card
{
   public Card()
   {
       Sides = new Collection<Side>();
       Stage = Stage.ONE;
   }

   [Key]
   [Required]
   public virtual int CardId { get; set; }

   [Required]
   public virtual Stage Stage { get; set; }

   [Required]
   [ForeignKey("CardId")]
   public virtual ICollection<Side> Sides { get; set; }
}

這是我的Side實體:

public class Side
{
   public Side()
   {
       Stage = Stage.ONE;
   }

   [Key]
   [Required]     
   public virtual int SideId { get; set; } 

   [Required]
   public virtual Stage Stage { get; set; }

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

   [ForeignKey("CardId")]
   public virtual Card Card { get; set; }

}

這是我的舞台實體:

public class Stage
{
   // Zero
   public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
   // Ten seconds
   public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");

   public static IEnumerable<Stage> Values
   {
       get
       {
           yield return ONE;
           yield return TWO;
       }

   }

   public int StageId { get; set; }
   private readonly TimeSpan span;
   public string Title { get; set; }

   Stage(TimeSpan span, string title)
   {
       this.span = span;
       this.Title = title;
   }

   public TimeSpan Span { get { return span; } }
}

奇怪的是,如果我在我的 Stage 類中添加以下內容:

   public int? SideId { get; set; }
   [ForeignKey("SideId")]
   public virtual Side Side { get; set; }

遷移成功執行。如果我打開 SSMS 並查看表格,我可以看到Stage_StageId已添加到Cards(如預期/期望),但Sides不包含對Stage(未預期)的引用。

如果我再添加

   [Required]
   [ForeignKey("StageId")]
   public virtual Stage Stage { get; set; }
   public int StageId { get; set; }

在我的 Side 課程中,我看到StageId我的表中添加了Side列。

這是有效的,但現在在我的整個應用程序中,任何對Stage包含 a 的引用SideId,在某些情況下是完全不相關的。 如果可能的話,我只想給我CardSide實體一個Stage基於上述 Stage 類的屬性,而不用引用屬性污染舞台類……我做錯了什麼?

因為Stagerequired,所以所有涉及的一對多關係Stage都將預設啟用級聯刪除。這意味著,如果您刪除一個Stage實體

  • 刪除將直接級聯到Side
  • 刪除將直接級聯到Card並且因為Card並且Side與預設啟用的級聯刪除具有必需的一對多關係,然後它將級聯CardSide

Stage因此,您有兩個從to的級聯刪除路徑Side- 這會導致異常。

您必須Stage在至少一個實體中設置可選(即[Required]從屬性中刪除Stage屬性)或使用 Fluent API 禁用級聯刪除(數據註釋不可能):

modelBuilder.Entity<Card>()
   .HasRequired(c => c.Stage)
   .WithMany()
   .WillCascadeOnDelete(false);

modelBuilder.Entity<Side>()
   .HasRequired(s => s.Stage)
   .WithMany()
   .WillCascadeOnDelete(false);

引用自:https://stackoverflow.com/questions/17127351