6

I'm attempting to set Entity Framework to cascade on delete with an optional foreign key. I'm using code first, and my model looks like this:

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

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

I've seen plenty of solutions that suggest, "Just make the foreign key required," but this will not work for me because the parent node may be null.

Does a solution exist that doesn't involve manually deleting child nodes before parent nodes?

Charles W
  • 2,262
  • 3
  • 25
  • 38

2 Answers2

3

Is this what you are looking for?

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

From the above, it would be something like (but I have not tried it):

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{

    modelBuilder.Entity<Node>()
        .HasOptional(a => a.Parent)
        .WithOptionalDependent()
        .WillCascadeOnDelete(true);
}
Community
  • 1
  • 1
user25398
  • 101
  • 5
  • 1
    Unfortunately that does not work for me. The relationship I've defined is self-referencing, and apparently MSSQL does not support cascade for self-referencing foreign-keys. Otherwise, that would normally work. Thanks! – Charles W Apr 04 '14 at 17:57
  • 1
    Worked, but needed to replace WithOptionalDependent with WithMany(a => a.Childs) – AXMIM Feb 10 '16 at 19:42
2

It looks as though MSSQL is to blame here. Because my table is self-referencing, It is impossible to set cascade on delete to true.

Instead, what I ended up doing was manually marking each child for deletion recursively, then calling SaveChanges() and letting EntityFramework sort out the rest.

Here is a simple code sample to illustrate:

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();
    }
}
Charles W
  • 2,262
  • 3
  • 25
  • 38