FOREIGN KEY制約を導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります。なぜでしょうか? 質問する

FOREIGN KEY制約を導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります。なぜでしょうか? 質問する

私はしばらくこの問題に取り組んできましたが、何が起こっているのかよくわかりません。私は Sides (通常 2) を含む Card エンティティを持っています。そして、Cards と Sides の両方に Stage があります。私は EF Codefirst 移行を使用していますが、移行は次のエラーで失敗します:

テーブル 'Sides' に FOREIGN KEY 制約 'FK_dbo.Sides_dbo.Cards_CardId' を導入すると、サイクルまたは複数のカスケード パスが発生する可能性があります。ON DELETE NO ACTION または ON UPDATE NO ACTION を指定するか、他の FOREIGN KEY 制約を変更してください。

これが私のカードエンティティです:

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; }
}

これが私のサイドエンティティです:

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; }

Stage_StageId移行は正常に実行されます。SSMS を開いてテーブルを確認すると、が追加されていることがわかりますCards(予想どおり/希望どおり)。ただし、Sidesへの参照は含まれていませんStage(予想外)。

次に

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

サイドクラスでは、テーブルStageIdに列が追加されていることがわかりますSide

これは機能していますが、アプリケーション全体で、 への参照に がStage含まれておりSideId、これは場合によってはまったく無関係です。可能であれば、ステージ クラスを参照プロパティで汚染することなく、およびエンティティに上記のステージ クラスに基づくプロパティを与えたいのですCardSideStageが...何が間違っているのでしょうか?

ベストアンサー1

Stage必須であるため、 が関係するすべての1対多関係ではStage連鎖削除がデフォルトで有効になります。つまり、Stageエンティティを削除すると

  • 削除は直接カスケードされますSide
  • 削除は に直接カスケードしますCard。 とCardSide必須の1対多の関係を持ち、カスケード削除がデフォルトで有効になっているため、 から にカスケードしますCardSide

Stageしたがって、からへの 2 つのカスケード削除パスがありSide、例外が発生します。

Stage少なくとも 1 つのエンティティでオプションにする (つまり、プロパティ[Required]から属性を削除するStage) か、Fluent API を使用してカスケード削除を無効にする (データ注釈では不可能)必要があります。

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

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

おすすめ記事