【问题标题】:How do you set Entity Framework to cascade on delete with optional foreign key?您如何将实体框架设置为使用可选外键删除时级联?
【发布时间】:2014-04-02 15:08:20
【问题描述】:

我正在尝试将实体框架设置为使用可选外键删除时级联。我先用代码,我的模型是这样的:

public class Node
{
    [Key]
    public int ID { get; set; }

    [ForeignKey("Parent")]
    public int? ParentID { get; set; }
    public virtual Node Parent { get; set; }
}

我看到很多解决方案建议“只需要设置外键”,但这对我不起作用,因为父节点可能为空。

是否存在不涉及在父节点之前手动删除子节点的解决方案?

【问题讨论】:

    标签: c# entity-framework ef-code-first


    【解决方案1】:

    这就是你要找的吗?

    Entity Framework (EF) Code First Cascade Delete for One-to-Zero-or-One relationship

    从上面看,它会是这样的(但我没有尝试过):

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    
        modelBuilder.Entity<Node>()
            .HasOptional(a => a.Parent)
            .WithOptionalDependent()
            .WillCascadeOnDelete(true);
    }
    

    【讨论】:

    • 不幸的是,这对我不起作用。我定义的关系是自引用的,显然 MSSQL 不支持自引用外键的级联。否则,这通常会起作用。谢谢!
    • 有效,但需要将 WithOptionalDependent 替换为 WithMany(a => a.Childs)
    【解决方案2】:

    看起来好像是 MSSQL 应该归咎于此。因为我的表是自引用的,所以无法将删除时的级联设置为true。

    相反,我最终做的是手动标记每个子项以递归方式删除,然后调用 SaveChanges() 并让 EntityFramework 整理其余部分。

    下面是一个简单的代码示例来说明:

    void Delete(bool recursive = false)
    {
        if(recursive)
            RecursiveDelete();
    
        if(this.Parent != null)
            this.Parent.Children.Remove(this);
    
        using(var db = new MyContext())
        {
            db.SaveChanges();
        }
    }
    void RecursiveDelete()
    {
        foreach(var child in Children.ToArray())
        {
            child.RecursiveDelete();
            Children.Remove(child);
        }
    
        using(var db = new MyContext())
        {
            db.Nodes.Attach(this);
            db.Entry(this).State = EntityState.Deleted();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 2016-10-22
      • 1970-01-01
      • 2014-12-20
      相关资源
      最近更新 更多