Missing EF Feature Workarounds: Cascade delete orphans

Currently, Entity Framework cannot cascade delete orphans. In fact, there’s not a real concept of parent-child relationships, there’s only navigation properties, collection properties, and a notion of required/optional relationships. You can cascade delete if a parent is deleted, but if you try something like this:

var customer = dbContext.Customers.Find(10);



// We now have an orphaned Address!

You’ll have an orphaned address! In a parent-child relationship, you’d like the parent to completely own the relationship to the child. Children cannot live on their own, so even if you configure EF to have a required relationship from child to parent:

public class CustomerContext : DbContext {
    protected override OnModelCreating(DbModelBuilder modelBuilder) {
            .HasRequired(a => a.Customer);

You’ll get an error on SaveChanges about a required relationship not being available. What we’d like to do is when true child entities get detached from their parent, they get deleted. There’s no way to do this in the entity mapping, but we can override SaveChanges in our custom DbContext class to detect orphans and then delete them:

public class CustomerContext : DbContext {
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Address> Addresses { get; set; }
    public override int SaveChanges() {
        foreach (var orphan in Addresses.Local.Where(a => a.Customer == null)) {

Not terrible, but it preserves the encapsulation of my parent-child relationship from Customer and Address.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in EntityFramework. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Harry McIntyre

    Sometime I wonder if parent-child for aggregate modelling would be a good idea to have implemented as a language feature.

    • jbogard

      Tough because we can’t ignore the DB modeling, though.

  • Bob Archer

    Isn’t this only going to work if you included the Children in the original query or you have lazy loading enabled? This should be controlled by cascade deletes in the database. Just because you’re using an ORM, don’t ignore the database server features.

    • jbogard

      This is a different kind of cascade delete – I want to delete *orphans*, when they’re detached from a parent. The parent is still around.

  • Brock Allen
    • jbogard

      Ah nice, thanks!

      • Mark Bouwman

        Did you manage to get this solution to work? The child collection always seems to be null. I tried to disable proxy generation and lazy loading but to no avail. It seems like ICollection properties are not yet populated when objects are added to the dbset.

  • jwdenny13

    I really like this solution but is it possible to add this behavior dynamically? In my current project we have a large database so it would be nice if SaveChanges() could dynamically figure out which tables fit this criteria and automatically remove the orphaned records.

  • Pingback: Missing EF Feature Workarounds: Cascade delete orphans | Dot Net RSS()

  • Trevor E

    If I may tag on to this discussion, this resolved my error:

    The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted

    I thought it might be helpful if this text was tagged to this article so guys like me could find it while googling for the error. The guys at Arana pointed me to this article or I would have never found it.

  • Fzznik

    I found very recently an even simpler solution with EF6. No need to override SaveChanges, specify CascadeOnDelete, or bind any event handlers to your DbContext. The simple trick is to make the relationship between Customers and Addresses an “identifying relationship,” and EF will know when you remove the address from the customer (making it an orphan), that the record should be deleted.

    What this means (in your example) is that the primary key on the Addresses table would be composite, including both the AddressID and the CustomerID. (You can still have AddressID be an auto-incrementing Identity field.)

    // A composite key on the Address like this indicates we have an “identifying relationship”
    modelBuilder.Entity().HasKey(a => new { a.AddressID, a.CustomerID });
    // And for keeping the auto-increment field, if using one:

    More info : http://msdn.microsoft.com/en-us/library/ee373856.aspx

    • Fzznik

      Whoops, the last line I wrote for keeping the auto-incrementing field forgot to include .Property(a => a.AddressID) in front of the HasDatabaseGeneratedOption…

      .Property(a => a.AddressID)

    • Reddy I. Bell

      Nice trick, but then it is necessary that Address have a reference to Customer. However you are likely to use this Address class for various objects, so I think that Address shouldn’t have any knowledge of other objects

      • jbogard

        “However you are likely to use this Address class for various objects” <- Not unless there is a single table for Address, which I consider pretty unlikely.

        • Reddy I. Bell

          I agree with you, but beyond this example I think there might be cases where the dependent of a one-to-many relationship doesn’t have any knowledge of the principal

          • jbogard

            I’m with you there – though personally I still prefer to have many-to-one be the default until I *absolutely need* one-to-many represented in my model.

          • Reddy I. Bell

            Thanks, I’ll keep that in mind but I’m curious, what are the benefits of doing so ? (beside the fact that it’s massively helpful here)

          • jbogard

            I don’t like collection navigations unless the parent truly owns the child or a query explicitly needs it – I’d rather navigate the other direction from the root entity in my query.

            It’s too easy with collection navigations to really explode out results, so I prefer to be explicit about starting with a root entity and navigating outward through FK relationships.

          • Reddy I. Bell

            That makes sense!

    • Jobran Jubair

      Thank you so much, it worked like magic

  • Hi Jimmy,
    I have used your solution.But it didn’t work.Could you tell me why ? Here is the SOF link.Thanks.