Getting Started with Entity Framework Extensions in 5 Minutes

If you've ever worked with Entity Framework Core on a real-world project, you've probably hit the wall: inserting, updating, or deleting thousands of rows is painfully slow. That's because EF Core sends one SQL command per entity by default.
Entity Framework Extensions solves this problem by providing high-performance bulk operations that can make your data access layer 2x to 5x faster — often with just a single line of code.
In this article, I'll show you how to get started with Entity Framework Extensions in just 5 minutes.
Why SaveChanges Is Slow
Let's start with a common scenario. You need to insert 10,000 customers into your database:
var customers = GenerateCustomers(10_000); context.Customers.AddRange(customers); await context.SaveChangesAsync();
This looks simple, but under the hood, EF Core generates 10,000 individual INSERT statements. Each one is sent to the database separately. The result? What should take milliseconds can take 30+ seconds.
The problem gets even worse with updates and deletes — EF Core must first load entities into the change tracker, detect changes, and then send individual commands for each modified row.
Enter Entity Framework Extensions
Entity Framework Extensions is a library by ZZZ Projects that extends EF Core with bulk and batch operations. It works directly with your existing EF Core model — no extra configuration, no changes to your entities.
Installation
Install the NuGet package:
dotnet add package Z.EntityFramework.Extensions.EFCore
Add the using directive:
using Z.EntityFramework.Extensions;
That's it. You're ready to go.
BulkSaveChanges: The Easiest Performance Win
The fastest way to boost performance is to replace SaveChanges with BulkSaveChanges. It works exactly the same way — it processes all tracked changes — but uses optimized bulk operations under the hood:
var customers = GenerateCustomers(10_000); context.Customers.AddRange(customers); await context.BulkSaveChangesAsync(); // That's it!
One line changed, and you can expect a 2x–5x improvement depending on the number of entities and your database provider.
You can also customize the behavior:
await context.BulkSaveChangesAsync(options => { options.BatchSize = 1000; });
Bulk Operations for Maximum Control
When you need even more performance or want to work with detached entities, use the dedicated bulk methods:
BulkInsert
var customers = GenerateCustomers(10_000); await context.BulkInsertAsync(customers);
BulkUpdate
var customers = await context.Customers.ToListAsync(); foreach (var customer in customers) { customer.IsActive = true; } await context.BulkUpdateAsync(customers);
BulkDelete
var inactiveCustomers = await context.Customers .Where(c => !c.IsActive) .ToListAsync(); await context.BulkDeleteAsync(inactiveCustomers);
BulkMerge (Upsert)
BulkMerge inserts new records and updates existing ones in a single operation — also known as an upsert:
var customers = GetCustomersFromExternalSource(); await context.BulkMergeAsync(customers);
You can customize the key used for matching:
await context.BulkMergeAsync(customers, options =>
{
options.ColumnPrimaryKeyExpression = c => c.Code;
});
Real-World Performance Comparison
Here's what you can expect when inserting entities with SQL Server (based on benchmarks from the official repository):
| Entities | SaveChanges | BulkInsert | Improvement |
|---|---|---|---|
| 1,000 | ~2s | ~200ms | ~10x |
| 10,000 | ~20s | ~600ms | ~33x |
| 100,000 | ~200s | ~3s | ~65x |
The library supports SQL Server, PostgreSQL, MySQL, MariaDB, Oracle, and SQLite.
What About Memory?
Performance isn't just about speed — memory usage matters too, especially in production under load.
Standard SaveChanges loads every entity into the EF Core change tracker, which consumes significant memory. Bulk operations like BulkUpdate and BulkDelete can bypass the change tracker entirely, and with features like IncludeGraph, you can reduce memory usage by up to 80% compared to SaveChanges.
Key Takeaways
- Replace
SaveChangeswithBulkSaveChangesfor an instant performance boost with zero refactoring. - Use dedicated bulk methods (
BulkInsert,BulkUpdate,BulkDelete,BulkMerge) when you need maximum control and performance. - No model changes required — the library works with your existing EF Core entities and configuration.
- Supports all major providers — SQL Server, PostgreSQL, MySQL, MariaDB, Oracle, and SQLite.
Conclusion
Entity Framework Extensions is one of those libraries that makes you wonder why you didn't use it sooner. If your application deals with batch data processing, imports, synchronization, or any scenario involving more than a handful of entities, the performance gains are substantial.
The best part? You can start with BulkSaveChanges as a drop-in replacement and explore more advanced features as your needs grow.
Useful links:
