BulkSynchronize in EF Core: Mirror Your Data in One Operation - Chris Woody Woodruff
EF Core lacks a native method for mirroring a list to a database table. The hand-rolled diff-and-apply pattern (load, classify, insert/update/delete, SaveChanges) works but loads all rows into the change tracker, scales poorly, and is error-prone. Entity Framework Extensions (EFE) provides BulkSynchronize, which stages the source list in a temp table and runs a server-side MERGE to insert new rows, update changed rows, and delete rows absent from the source — all in one transaction without materializing existing rows in .NET memory. The key configuration option is ColumnSynchronizeDeleteKeySubsetExpression, which scopes the delete branch to a specific slice of the table (e.g., by SupplierId or TenantId) to avoid accidentally removing unrelated rows. Benchmarks show BulkSynchronize is 4–5x faster than the hand-rolled approach at 100K rows. The post covers four practical scenarios (API cache sync, reporting table refresh, reference table mirror, per-tenant sync), important production gotchas (change tracker staleness, FK constraints, interceptors not firing), and an honest assessment of when the paid EFE license is justified.