引入 FOREIGN KEY 约束可能会导致循环或多个级联路径 - 为什么? [英] Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?

查看:25
本文介绍了引入 FOREIGN KEY 约束可能会导致循环或多个级联路径 - 为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为此纠结了一段时间,但无法弄清楚发生了什么.我有一个包含 Sides(通常为 2)的 Card 实体 - Cards 和 Sides 都有一个 Stage.我正在使用 EF Codefirst 迁移,迁移失败并出现此错误:

I've been wrestling with this for a while and can't quite figure out what's happening. I have a Card entity which contains Sides (usually 2) - and both Cards and Sides have a Stage. I'm using EF Codefirst migrations and the migrations are failing with this error:

引入 FOREIGN KEY 约束 'FK_dbo.Sides_dbo.Cards_CardId' on表边"可能会导致循环或多个级联路径.指定开启DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY约束.

Introducing FOREIGN KEY constraint 'FK_dbo.Sides_dbo.Cards_CardId' on table 'Sides' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

这是我的卡片实体:

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

}

这是我的 Stage 实体:

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 类中:

What's odd is that if I add the following to my Stage class:

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

迁移运行成功.如果我打开 SSMS 并查看表格,我可以看到 Stage_StageId 已添加到 Cards(如预期/所需),但是 Sides> 不包含对 Stage 的引用(不是预期的).

The migration runs successfully. If I open up SSMS and look at the tables, I can see that Stage_StageId has been added to Cards (as expected/desired), however Sides contains no reference to Stage (not expected).

如果我再添加

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

对于我的 Side 类,我看到 StageId 列添加到我的 Side 表中.

To my Side class, I see StageId column added to my Side table.

这是有效的,但现在在我的整个应用程序中,对 Stage 的任何引用都包含一个 SideId,这在某些情况下是完全不相关的.我只想给我的 CardSide 实体一个基于上述 Stage 类的 Stage 属性而不污染舞台类如果可能,使用参考属性...我做错了什么?

This is working, but now throughout my application, any reference to Stage contains a SideId, which is in some cases totally irrelevant. I'd like to just give my Card and Side entities a Stage property based on the above Stage class without polluting the stage class with reference properties if possible... what am I doing wrong?

推荐答案

因为Stage必需的Stage的所有一对多关系代码> 将默认启用级联删除.这意味着,如果你删除一个 Stage 实体

Because Stage is required, all one-to-many relationships where Stage is involved will have cascading delete enabled by default. It means, if you delete a Stage entity

  • 删除将直接级联到Side
  • 删除将直接级联到 Card 并且因为 CardSide 具有必需的一对多关系,通过以下方式启用级联删除再次默认它然后将从 Card 级联到 Side
  • the delete will cascade directly to Side
  • the delete will cascade directly to Card and because Card and Side have a required one-to-many relationship with cascading delete enabled by default again it will then cascade from Card to Side

因此,您有两个从 StageSide 的级联删除路径 - 这会导致异常.

So, you have two cascading delete paths from Stage to Side - which causes the exception.

您必须在至少一个实体中将 Stage 设为可选(即从 Stage 属性中删除 [Required] 属性) 或使用 Fluent API 禁用级联删除(无法使用数据注释):

You must either make the Stage optional in at least one of the entities (i.e. remove the [Required] attribute from the Stage properties) or disable cascading delete with Fluent API (not possible with data annotations):

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

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

这篇关于引入 FOREIGN KEY 约束可能会导致循环或多个级联路径 - 为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆