I’m using EF Core 3.1.1, but I believe this question applies to all versions of EF.
It seems the EF has the ability to cascade delete - if it is enabled, and if the dependent objects are loaded in the context.
var blog = context.blogs.Include(x => x.Posts).First(x => x.BlogId == id);
context.blogs.Remove(blog);
The above statement deletes all the blog’s posts, and then the blog - each with a different sql statement.
This is what I want, however when using code-first, it also creates the tables with cascading delete enabled in the database. (ON DELETE CASCADE
)
Can you enable cascade delete in EF, and rely of EF deleting dependent objects, without also enabling database level cascade delete? (Or am I understanding this incorrectly?)
The reason is migrations fail because SQL won’t enable cascade delete in the database because it detects multiple cascade paths (even though multiple wouldn’t occur naturally in the schema)
Thanks!
Actually EF Core 3.0 is the first version of EF which adds such capability via DeleteBehavior.ClientCascade option (unfortunately not yet included in the Cascade Delete section of the documentation):
For entities being tracked by the
DbContext
, dependent entities will deleted when the related principal is deleted.If the database has been created from the model using Entity Framework Migrations or the
EnsureCreated()
method, then the behavior in the database is to generate an error if a foreign key constraint is violated.
Shortly, all Client*
delete behaviors are mapped to Restrict
, i.e. enforced FK relationship in database without cascade. Client behavior apply only on entities tracked by the context, so make sure you Include
the related data before deleting (as in your sample).
To configure the option, you'd need fluent API at minimum having valid Has
+ With
in order to get to OnDelete
method, e.g.
modelBuilder.Entity<Blog>()
.HasMany(e => e.Posts)
.WithOne(e => e.Blog)
.OnDelete(DeleteBehavior.ClientCascade);
You can add the Cascade Behavior to your entities as below. inside OnModelCreating;
foreach (var foreignKey in builder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
foreignKey.DeleteBehavior = DeleteBehavior.Cascade;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With