Bulk SaveChangesSupercharge your EF Core SaveChanges by adding 'Bulk'
The BulkSaveChanges method works like EF Core’s SaveChanges method—only faster! It saves to the database all entities in your ChangeTracker that have one of the following states: Added, Modified, or Deleted.
// @nuget: Z.EntityFramework.Extensions.EFCore using Z.EntityFramework.Extensions; // Easy to use context.BulkSaveChanges(); // Easy to customize context.BulkSaveChanges(options => options.BatchSize = 100);
Online Example (EF Core) | Online Example (EF6)
💡 One key difference: If you provide an explicit identity value, you still need to use the InsertKeepIdentity = true option to tell our library to keep it.
Performance Comparison
| Operations | 1,000 Entities | 2,000 Entities | 5,000 Entities |
|---|---|---|---|
| SaveChanges | 1,200 ms | 2,400 ms | 6,000 ms |
| BulkSaveChanges | 150 ms | 225 ms | 500 ms |
Try it in EF Core | Try it in EF6
HINT:A lot of factors might affect the benchmark time such as index, column type, latency, throttling, etc.
What is supported?
- All Entity Framework Core Version: EF Core 9, EF Core 8, EF Core 7, EF Core 6, EF Core 5, EF Core 3
- All Entity Framework Version: EF6, EF5, EF4
- All Inheritances (TPC, TPH, TPT)
- Complex Type/Owned Entity Type
- Enum
- Value Converter (EF Core)
- And more!
Advantages
- Easy to use
- Flexible
- Increase performance
- Increase application responsiveness
- Reduce database load
- Reduce database round-trips
FAQ
Why BulkSaveChanges is faster than SaveChanges?
The SaveChanges method makes it quite slow/impossible to handle a scenario that requires to save a lot of entities due to the number of database round-trips required. The SaveChanges performs one database round-trip for every entity to insert. So, if you need to insert 10,000 entities, 10,000 database round-trips will be performed which is INSANELY slow.
The BulkSaveChanges in counterpart requires the minimum number of database round-trips possible. By using Bulk Operations, fewer commands are executed which lead to better performance.
Why BulkSaveChanges update all columns by default (EF6 only)?
The BulkSaveChanges tries to combine most commands in a single operation. Updating different columns from an action to another will require generating different SQL and being executed in several database round-trips.
That's still possible to have the same behavior of SaveChanges by disabling the option ForceUpdateUnmodifiedValues:
ctx.BulkSaveChanges(options => options.ForceUpdateUnmodifiedValues = false);
For EF Core, this option is not available. Only columns that have a modification will be saved exactly like SaveChanges.
When should I use BulkSaveChanges over SaveChanges?
Whenever you have more than one entity to save. The BulkSaveChanges is almost as fast as the SaveChanges for one entity, but becomes way faster as the number of entities to save grows.
When should I use BulkSaveChanges over BatchSaveChanges?
BatchSaveChanges become slower and slower in comparison to BulkSaveChanges when the number of entities to save grows due to the ChangeTracker.
After a few thousands of entities, we recommend using BulkSaveChanges which is a more scalable solution.
Documentation
BatchSaveChanges
Methods
| Name | Description | Example |
|---|---|---|
BulkSaveChanges() |
Save all changes made in this context to the underlying database by executing bulk operations. | EFCore / EF6 |
BulkSaveChanges(Action<BulkOperation> bulkOperationFactory) |
Save all changes made in this context to the underlying database by executing bulk operations. | EFCore / EF6 |
BulkSaveChanges(bool useEntityFrameworkPropagation) |
Save all changes made in this context to the underlying database by executing bulk operations. | EFCore / EF6 |
BulkSaveChanges(bool useEntityFrameworkPropagation, Action<BulkOperation> bulkOperationFactory) |
Save all changes made in this context to the underlying database by executing bulk operations. | EFCore / EF6 |
BulkSaveChangesAsync() |
Save all changes asynchronously made in this context to the underlying database by executing bulk operations. | EFCore / EF6 |
BulkSaveChangesAsync(Action<BulkOperation> bulkOperationFactory) |
Save all changes asynchronously made in this context to the underlying database by executing bulk operations. | EFCore / EF6 |
BulkSaveChangesAsync(bool useEntityFrameworkPropagation) |
Save all changes asynchronously made in this context to the underlying database by executing bulk operations. | EF6 |
BulkSaveChangesAsync(bool useEntityFrameworkPropagation, Action<BulkOperation> bulkOperationFactory) |
Save all changes asynchronously made in this context to the underlying database by executing bulk operations. | EF6 |
Options
More options can be found here:
- Audit
- Batch
- Column
- Context Factory
- Execute Event
- Identity
- Include Graph
- Key
- Logging
- Temporary Table
- Transaction
- Transient Error
- SQL Server
ZZZ Projects