We have an entity hierarchy with a root entity that has several collections of dependent entities (the collections are big enough), some of the dependents may have their own dependent entities, and so on.
When some entities are removed from the root's collections, the call of SaveChangesAsync is extremely slow. It seems that the slowdown is caused by change detection during cascade delete (because all parents and their navigation collections are checked). But it's possible to disable auto change detection, manually call DetectChanges before SaveChangesAsync and drastically increase performance:
using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
var db = new MainDbContext();
var first = new Root
{
Id = 1,
Children1 = Enumerable
.Range(1, 10)
.Select(i => new Child1
{
Id = i,
RootId = 1,
Children = Enumerable
.Range(1, 2000)
.Select(j => new Child11
{
Id = (i - 1) * 2000 + j,
Child1Id = i
})
.ToList()
})
.ToList(),
Children2 = Enumerable.Range(1, 30000).Select(i => new Child2 { Id = i, RootId = 1 }).ToList()
};
db.Add(first);
await db.SaveChangesAsync();
var watch = Stopwatch.StartNew();
first.Children1.RemoveAt(first.Children1.Count - 1);
// db.ChangeTracker.AutoDetectChangesEnabled = false;
// db.ChangeTracker.DetectChanges();
await db.SaveChangesAsync();
Console.WriteLine("{0}", watch.Elapsed);
internal class Root
{
public int Id { get; init; }
public List<Child1> Children1 { get; init; } = [];
public List<Child2> Children2 { get; init; } = [];
}
internal class Child1
{
public int Id { get; init; }
public int RootId { get; init; }
public List<Child11> Children { get; init; } = [];
}
internal class Child11
{
public int Id { get; init; }
public int Child1Id { get; init; }
}
internal class Child2
{
public int Id { get; init; }
public int RootId { get; init; }
}
internal class MainDbContext : DbContext
{
public DbSet<Root> Root { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseInMemoryDatabase("CascadeDeleteTest");
}
}
Version
EF Core: 8.0.8
Target framework: net8.0
Operating system: Ubuntu 24.04
We have an entity hierarchy with a root entity that has several collections of dependent entities (the collections are big enough), some of the dependents may have their own dependent entities, and so on. When some entities are removed from the root's collections, the call of
SaveChangesAsync
is extremely slow. It seems that the slowdown is caused by change detection during cascade delete (because all parents and their navigation collections are checked). But it's possible to disable auto change detection, manually callDetectChanges
beforeSaveChangesAsync
and drastically increase performance:Steps to reproduce
Version
EF Core: 8.0.8 Target framework: net8.0 Operating system: Ubuntu 24.04