EF Core's naive load-modify-save pattern causes severe performance issues at scale, allocating gigabytes of RAM and issuing one SQL statement per entity. EF Core 7+ introduced ExecuteUpdate and ExecuteDelete, which bypass the change tracker and execute a single server-side SQL statement regardless of row count. Benchmarks against 1M rows show these native methods are ~2-4x faster than the naive approach. For server-side INSERT...SELECT (table-to-table copy without loading entities), EF Core 10 still has no native equivalent — Entity Framework Extensions (EFE) fills this gap with InsertFromQuery, which achieves near-constant memory usage and ~22x speedup at 1M rows. Key caveats include stale tracked entities after batch ops, no interceptor/cascade firing, and the need for explicit transactions when mixing batch ops with SaveChanges.

13m read timeFrom woodruff.dev
Post cover image
Table of contents
The Code Every Developer Has Written and RegrettedThe Built-In Answer: ExecuteUpdate and ExecuteDeleteThe Missing Piece: There Is No ExecuteInsertEFE’s Batch Operations: UpdateFromQuery, DeleteFromQuery, InsertFromQueryBenchmarks: The Honest NumbersChoosing the Right ToolCaveats That Will Catch You Off-GuardConclusion

Sort: