Cascade delete with DbContext and Entity Framework 6


Question

Is there a way to cascade delete entities without modifying foreign keys in DB and without modifying edmx? I have DB with over 100 tables referenced using foreign keys with Delete Rule = No Action.

I found this this beautiful code in "Entity Framework 6 Recipes" book. But it for ObjectContext and I need for the DbContext.

    private static void DeleteRelatedEntities<T>(T entity, test123Entities1 context)
        where T : EntityObject
    {
        var entities =
            ((IEntityWithRelationships) entity).RelationshipManager.GetAllRelatedEnds()
                .SelectMany(e => e.CreateSourceQuery().OfType<EntityObject>())
                .ToList();

        foreach (var child in entities)
        {
            DeleteRelatedEntities(child, context);
            context.DeleteObject(child);
        }
        context.SaveChanges();
    } 

It's possible to use this method with this convertion

//var ddd = ((IObjectContextAdapter)context).ObjectContext;

but then I also need similar adapter to convert my POCO to EntityObject.

Any suggestions?

Thank you.

Popular Answer

That is BAD code.

  1. It even doesn't work. It fails with StackOverflowException - verified right now by copying your code snippet into my test solution.
  2. It is not cascade delete. Cascade delete happens in database (unless you already have entities loaded) but this code always executes queries on all navigation properties to load entities and mark them as deleted in your application. It creates terrible overhead by transferring all those data from DB to your app.
  3. The word all in previous paragraph really means all = it doesn't respect the normal flow of cascade delete (from parent to children). This method can also flow in reverse direction (from children to parent) and because it is recursive your parent's navigation properties will be loaded and deleted as well. It means that from child you can easily delete significant part of your database!!!
  4. If you have navigation property on both child and parent entity you will get into infinite loop!
  5. SaveChanges is called in recursive function - each execution will flush to database every unprocessed change from the context - not only changes done in that specific recursion step. It also requires TransactionScope if you want to keep everything in single atomic operation.
  6. This approach is a great way to introduce concurrency issues and worse - deadlocks to your application.
  7. It is dependent on EntityObject - OMG why book about EF6 contains code related to EntityObject class? Looks like a cash cow with content copied from old version about EF4. I don't have anything against ObjectContext API but EntityObject? Really?

In short make yourselves a favor and fix your DB and entity model if you want to have cascade delete or don't use cascade delete and manually (preferably with direct SQL) delete dependencies. There is also option to use triggers to execute that SQL but I don't consider triggers as a good option.





Licensed under: CC-BY-SA
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why