Post 转载可能会造成循环或多级联路径

Post Repost May cause cycles or multiple cascade paths

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


尝试 1


public class Post
{
    public int Id { get; set; }
    public string Text { get; set; }
    public int? RepostId { get; set; }
    public Post Repost { get; set; }
}

流利API

builder.Entity<Post>()
       .HasOne(s => s.Repost)
       .WithOne()
       .OnDelete(DeleteBehavior.SetNull);

尝试 2


public class Repost
{
    public Repost()
    {
        Posts = new HashSet<Post>();
    }

    public int Id { get; set; }
    public int? PostId { get; set; }
    public virtual Post? Post { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int Id { get; set; }
    public string Text { get; set; } = null!;
    public int? RepostId { get; set; }
    public virtual Repost? Repost { get; set; }
    public virtual Repost? RepostNavigation { get; set; }
}

流利API

builder.Entity<Post>(entity =>
        {
            entity.HasOne(d => d.Repost)
                .WithMany(p => p.Posts)
                .HasForeignKey(d => d.RepostId)
                .OnDelete(DeleteBehavior.SetNull)
                .HasConstraintName("FK_Posts_Posts");
        });

        builder.Entity<Repost>(entity =>
        {
            entity.ToTable("Repost");

            entity.HasIndex(e => e.PostId, "IX_Repost_PostId")
                .IsUnique();

            entity.HasOne(d => d.Post)
                .WithOne(p => p.RepostNavigation)
                .HasForeignKey<Repost>(d => d.PostId)
                .OnDelete(DeleteBehavior.Cascade);
        });

当我删除一个post时,我需要在repost中设置null。 我可以使用DeleteBehavior.NoAction,但问题是,有没有办法在post被删除时自动设置它?

UPD

解决方案

public class Post
{
    public int Id { get; set; }
    public string Text { get; set; }
    public int? RepostId { get; set; }
    public Post Repost { get; set; }
    public ICollection<Post> Reposts { get; set; }
}
    builder.Entity<Post>()
            .HasOne(s => s.Repost)
            .WithMany(s => s.Reposts)
            .HasForeignKey(s => s.RepostId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.ClientSetNull);

您的第一次尝试很接近,只是 self-references 或您的 属性 名称与显式配置 FK 所需的类型名称不同的任何引用:

这应该有效:

builder.Entity<Post>()
   .HasOne(s => s.Repost)
   .WithOne()
   .HasForeignKey<Post>(s => s.RepostId)
   .OnDelete(DeleteBehavior.ClientSetNull);

DeleteBehavior.SetNull 不是有效选项,因为 SQL 服务器无法解析 self-referencing FK 上的该行为。如果您尝试在 SQL 服务器中使用 ON DELETE SET NULL 设置 self-referencing FK,您会得到同样的错误。通过使用 ClientSetNull EF 可以在删除记录之前为任何相关实体发出更新语句。

SetNull 似乎可以工作 如果 DbContext 在删除相关实体时恰好跟踪了相关实体。