Efcore: How do I disable OneToMany and ManyToMany Cascade Delete as of rc1?

Created on 20 Nov 2015  路  11Comments  路  Source: dotnet/efcore

In EF6, I could do:
builder.Conventions.Remove();
builder.Conventions.Remove();

In previous iterations of EF7 it wasn't supported. But now that it's supported, I can't figure out how to turn it off globally.

Most helpful comment

If you want to change the delete behavior for all relationships, then you can use this code in OnModelCreating(...) to bulk set it for all relationships in your model.

foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
    relationship.DeleteBehavior = DeleteBehavior.Restrict;
}

All 11 comments

Wondering too.

I have disabled it manually on some relationships :

builder.Entity<Site>().HasOne(e => e.Person)
  .WithMany(x => x.Sites).Metadata.DeleteBehavior = DeleteBehavior.Restrict;

If you want to change the delete behavior for all relationships, then you can use this code in OnModelCreating(...) to bulk set it for all relationships in your model.

foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
    relationship.DeleteBehavior = DeleteBehavior.Restrict;
}

Excellent, thank you!

Thanks rowanmiller.

Thanks @rowanmiller. That's a nice work around

Here is how you default to Restrict for all except Identity Entities

List<IMutableEntityType> identiyEntities = new List<IMutableEntityType>
{
    modelBuilder.Model.FindEntityType(typeof(User)),
    modelBuilder.Model.FindEntityType(typeof(IdentityRole)),
    modelBuilder.Model.FindEntityType(typeof(IdentityUserRole<string>)),
    modelBuilder.Model.FindEntityType(typeof(IdentityUserClaim<string>)),
    modelBuilder.Model.FindEntityType(typeof(IdentityUserLogin<string>)),
    modelBuilder.Model.FindEntityType(typeof(IdentityUserToken<string>)),
    modelBuilder.Model.FindEntityType(typeof(IdentityRoleClaim<string>)),
};
foreach (var relationship in modelBuilder.Model.GetEntityTypes().Except(identiyEntities).SelectMany(e => e.GetForeignKeys()))
    relationship.DeleteBehavior = DeleteBehavior.Restrict;

@rowanmiller one little fix to your answer.

After the GetEntityTypes() method, is neccesary to add .Where(e => !e.IsOwned()) condition, if not, the complex objects of the entity will not be deleted. #10179

c# protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var relationship in modelBuilder.Model.GetEntityTypes().Where(e => !e.IsOwned()).SelectMany(e => e.GetForeignKeys())) { relationship.DeleteBehavior = DeleteBehavior.Restrict; } }

Don't do what i just did and forget to regenerate the migration too.
For some odd reason EF Core doesn't have the "telepathy extension" yet ... dam lazy devs!!!

Do what i mean and not what I write dam you !!!

Doesn't work any more, there is not .Where or .SelectMany method in the using Microsoft.EntityFrameworkCore; I am getting compilation errors. Could someone please help?

Data/SpmDbContext.cs(15,78): error CS1061: 'IEnumerable' does not contain a definition for 'SelectMany' and no accessible extension method 'SelectMany' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?)

@raygao

using System.Linq;

I have that include, and it still does not work.
My code is below. All I want to do is to set global restrict instead of disabling cascading delete per entity.
// protected override void OnModelCreating(ModelBuilder modelBuilder)
// {
// foreach (var entity in modelBuilder.Model.GetEntityTypes())
// {
// foreach (var relationship in entity.GetProperties().SelectMany(t => t.GetContainingForeignKeys()))
// {
// relationship.DeleteBehavior = DeleteBehavior.Restrict;
// }
// }
// base.OnModelCreating(modelBuilder);
// }

Was this page helpful?
0 / 5 - 0 ratings