Entity Framework Pitfalls: Cascade Deletes

Introduction

Entity Framework supports cascading deletes for all of its associations:

  • One to one
  • One to many
  • Many to many

Meaning, when we remove an entity, it will automatically descend to its dependent entities (cascade) and delete them too.

Of course, cascading deletes of many to one really does not make much sense. The problem with cascade deletes configuration in EF is, sometimes it cannot be done with attributes, which is a mapping mechanism that most people like and use, and the different associations need different approaches.

One to One

For one to one relations, we need to use code mappings, say, we have an entity Master associated with a dependent entity Detail:

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

    modelBuilder

        .Entity<Master>()

        .HasOptional(x => x.Detail)

        .WithRequired(x => x.Master)

        .WillCascadeOnDelete(true);

 

    base.OnModelCreating(modelBuilder);

}

Deleting a Master will also delete the Detail, but, of course, not the other way around. If you are curious, EF does this through an ON DELETE CASCADE INDEX, so it is done by the database, not by EF – more on this later.

image

One to Many

We just need to mark the one endpoint with a [Required] attribute, like in a Detail entity that is a child of a Master:

public class Detail

{

    public int Id { get; set; }

 

    [Required]

    public virtual Master Master { get; set; }

}

This way, when we delete the Master entity, it will first delete all of its related Detail entities. This is also achieved through the automatically created ON DELETE CASCADE INDEX.

It is also certainly possible to achieve this using code configuration, but not really necessary – and more verbose:

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

    modelBuilder

        .Entity<Master>()

        .HasMany(x => x.Details)

        .WithRequired(x => x.Master)

        .WillCascadeOnDelete();

 

    base.OnModelCreating(modelBuilder);

}

Many to Many

This one is the best: guess what, we don’t have to do anything, it just works out of the box!

Conclusion

Because Entity Framework relies on INDEXes to cascade the deletes, you cannot just change the code mappings after you created the model – either by adding attributes or through fluent configuration – and expect things to work. If you do, you will likely need to update the database. Do so by creating and applying a new migration. One thing that is still (as of EF 6.x) not supported is deleting orphans, but I already talked about it. EF Core will handle it properly.

Published by

Ricardo Peres

Team Leader at Dixons Carphone. Microsoft MVP.

Leave a Reply

Your email address will not be published. Required fields are marked *