引入外键约束可能会导致循环或多个级联路径-为什么?

jtjikinw  于 2022-09-18  发布在  Java
关注(0)|答案(19)|浏览(127)

我已经在这件事上挣扎了一段时间,不太明白发生了什么。我有一个卡片实体,它包含两个侧面(通常是2个)-并且卡片和侧面都有一个舞台。我正在使用EF CodeFirst迁移,迁移失败,错误如下:
在表‘side’上引入外键约束‘fk_dbo.sids_dbo.Cards_CardID’可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他外键约束。

这是我的卡片实体:

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

在我的边类中,我看到StageId列添加到我的Side表中。

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

mxg2im7a

mxg2im7a16#

您可以将CascadeDelete设置为FALSE或TRUE(在迁移up()方法中)。这要看你的要求了。

AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false);
z8dt9xmd

z8dt9xmd17#

当我从EF7模型向下迁移到EF6版本时,我收到了许多实体的这个错误。我不想一次一个地遍历每个实体,所以我使用:

builder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
builder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
dced5bon

dced5bon18#

任何人想知道如何在EF核心中做到这一点:

protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
                {
                    relationship.DeleteBehavior = DeleteBehavior.Restrict;
                }
           ..... rest of the code.....
ppcbkaq5

ppcbkaq519#

我有一个与其他人有循环关系的表,我也收到了同样的错误。事实证明,这是关于不能为空的外键的。如果键不可为空,则必须删除相关对象,循环关系不允许这样做。因此使用可以为空的外键。

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

相关问题