Entity Framework Extensions Bulk Extensions for EF Core with Entity Framework Extensions

Bulk Extensions are high-performance extension methods added to EF Core by Entity Framework Extensions. They are designed to speed up your CRUD operations and dramatically reduce memory usage in your application. These bulk methods are both easy to use and easy to customize.

Here’s an example of how to bulk insert in EF Core a list of Invoice entities along with their related InvoiceItems, using the IncludeGraph option:

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

context.BulkInsert(invoices, options => { options.IncludeGraph = true; });

The BulkInsert method from Entity Framework Extensions is not only much faster than using SaveChanges, it also reduces memory consumption.

πŸš€ Performance Benchmark

Let’s compare the performance of Entity Framework Extensions to EF Core SaveChanges method:

10k Invoices, 50k InvoiceItems:

IncludeGraph SaveChanges
Performance 1.5s 6s
Memory 60 MB 200 MB

100k Invoices, 500k InvoiceItems:

IncludeGraph SaveChanges
Performance 10s 58s
Memory 400 MB 1800 MB

With Entity Framework Extensions, you can boost performance by more than 5x and reduce memory usage to just 20% of what SaveChanges consumes.

Which Bulk Methods Does Entity Framework Extensions Support?

Whether you need to save or query data in bulk, Entity Framework Extensions provides a complete set of high-performance bulk methods to match your needs:

  • Saving

    • BulkInsert β€” Insert thousands of entities quickly and efficiently.
    • BulkUpdate β€” Update large sets of entities without having to retrieve them first.
    • BulkDelete β€” Delete many entities without the performance hit of SaveChanges.
    • BulkMerge β€” Insert or update in one smart operation (also known as upsert).
    • BulkSynchronize β€” Sync your list with the database by adding, updating, and deleting in one step.
    • BulkSaveChanges β€” Save all pending changes in one high-performance batch.
  • Querying

    • BulkRead β€” Efficiently read a large number of entities from the database.
    • WhereBulkContains β€” Filter a database table to return only rows that match the entities in your list.
    • WhereBulkNotContains β€” Filter a database table to return only rows that don’t match the entities in your list.
    • WhereBulkContainsFilterList β€” Filter your in-memory list to return only items that match rows in the database.
    • WhereBulkNotContainsFilterList β€” Filter your in-memory list to return only items that don’t match rows in the database.

Which Versions of Entity Framework Are Supported?

In short, all versions of EF Core and Entity Framework are supported:

  • Entity Framework Core: EF Core 9 and earlier
  • Entity Framework: EF6 and earlier

Which Providers Are Supported by Entity Framework Extensions?

Entity Framework Extensions supports all major providers available in EF Core, including:

  • SQL Server
  • MySQL
  • MariaDB
  • Oracle
  • PostgreSQL
  • SQLite

Bulk Insert β€” For EF Core with Entity Framework Extensions

The EF Core BulkInsert method from Entity Framework Extensions is one of the core features of the library. It allows you to insert thousands or even millions of entities into your database quickly and efficiently.

πŸ”§ Commonly Used Options

  • AutoMapOutputDirection β€” Improves performance by skipping the return of output values like identity columns.
  • InsertIfNotExists β€” Inserts only the entities that don't already exist in the database.
  • InsertKeepIdentity β€” Allows inserting custom identity values instead of letting the database generate them.
  • IncludeGraph β€” Automatically inserts related entities found in the object graph and preserves their relationships.

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Simple bulk insert
context.BulkInsert(customers);

// Bulk insert with options
context.BulkInsert(customers, options =>
{
    options.AutoMapOutputDirection = false;
    options.InsertIfNotExists = true;
});

// Bulk insert from anonymous list
context.BulkInsert<Customer>(anonymousList);

// Bulk insert async version
await context.BulkInsertAsync(customers);

Bulk Update β€” For EF Core with Entity Framework Extensions

The EF Core BulkUpdate method from Entity Framework Extensions allows you to update large sets of data in your database efficiently and with full control.

πŸ”§ Commonly Used Options

  • ColumnPrimaryKeyExpression β€” Use a custom key expression to identify which entities should be updated.
  • ColumnInputExpression β€” Specify which columns to update using a LINQ expression.
  • ColumnInputNames β€” Specify which columns to update by listing their names as strings.
  • IncludeGraph β€” Automatically updates related entities found in the object graph, preserving relationships.

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Simple bulk update
context.BulkUpdate(customers);

// Bulk update specific columns using an expression
context.BulkUpdate(customers, options =>
{
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };
});

// Bulk update from an anonymous list
context.BulkUpdate<Customer>(anonymousList);

// Bulk update async version
await context.BulkUpdateAsync(customers);

Bulk Delete β€” For EF Core with Entity Framework Extensions

The EF Core BulkDelete method from Entity Framework Extensions allows you to delete large sets of data from your database efficiently in one operation.

πŸ”§ Commonly Used Options

  • ColumnPrimaryKeyExpression β€” Use a custom key to identify which entities should be deleted.
  • DeleteMatchedAndConditionExpression β€” Delete only when all specified values from the source and destination match.
  • DeleteMatchedAndOneNotConditionExpression β€” Delete only when at least one specified value from the source differs from the destination.
  • DeleteMatchedAndFormula β€” Apply a SQL condition to decide whether or not to delete each entity.

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Simple bulk delete
context.BulkDelete(customers);

// Bulk delete with a custom SQL condition
context.BulkDelete(customers, options =>
{
    options.DeleteMatchedAndFormula = "DestinationTable.CreatedDate < DATEADD(YEAR, -2, GETDATE())";
});

// Bulk delete from an anonymous list
context.BulkDelete<Customer>(anonymousList);

// Bulk delete async version
await context.BulkDeleteAsync(customers);

Bulk Merge / Upsert β€” For EF Core with Entity Framework Extensions

The EF Core BulkMerge method from Entity Framework Extensions lets you insert or update data in bulk β€” depending on whether the record already exists. This feature is often referred to as Upsert, AddOrUpdate, or InsertOrUpdate.

πŸ”§ Commonly Used Options

  • ColumnPrimaryKeyExpression β€” Use a custom key expression to determine if an entity already exists in the database.
  • IgnoreOnMergeInsertExpression β€” Exclude specific columns during the insert phase of the merge operation.
  • IgnoreOnMergeUpdateExpression β€” Exclude specific columns during the update phase of the merge operation.
  • IncludeGraph β€” Automatically handles related entities in the object graph and preserves data relationships.

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Simple bulk merge (upsert)
context.BulkMerge(customers);

// Bulk merge with options
context.BulkMerge(customers, options =>
{
    options.ColumnPrimaryKeyExpression = x => new { x.Code };
    options.IgnoreOnMergeInsertExpression = x => new { x.UpdatedDate, x.UpdatedBy };
    options.IgnoreOnMergeUpdateExpression = x => new { x.CreatedDate, x.CreatedBy };
});

// Bulk merge from an anonymous list
context.BulkMerge<Customer>(anonymousList);

// Bulk merge async version
await context.BulkMergeAsync(customers);

Bulk Synchronize β€” For EF Core with Entity Framework Extensions

The EF Core BulkSynchronize method from Entity Framework Extensions allows you to insert, update, or delete data in your database in bulk β€” all in one operation. In other words, your database table becomes a mirror of the list of entities you provide.

This feature is often searched for under names like AddOrUpdateOrDelete or InsertOrUpdateOrDelete.

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Simple bulk synchronize (upsert)
context.BulkSynchronize(customers);

// Bulk synchronize with options
context.BulkSynchronize(customers, options => { /* custom settings here */ });

// Bulk synchronize from an anonymous list
context.BulkSynchronize<Customer>(anonymousList);

// Bulk synchronize async version
await context.BulkSynchronizeAsync(customers);

Bulk SaveChanges β€” For EF Core with Entity Framework Extensions

The EF Core BulkSaveChanges method from Entity Framework Extensions is a high-performance replacement for the standard SaveChanges method. It processes inserts, updates, and deletes β€” just like SaveChanges β€” but runs them much faster.

The only thing you need to change? Replace SaveChanges with BulkSaveChanges β€” and you're done!

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Standard EF Core
// context.SaveChanges();

// Improved performance with BulkSaveChanges
context.BulkSaveChanges();

// BulkSaveChanges with custom options
context.BulkSaveChanges(options => { /* custom settings */ });

// BulkSaveChanges async version
await context.BulkSaveChangesAsync();

Bulk Read β€” For EF Core with Entity Framework Extensions

The EF Core BulkRead method from Entity Framework Extensions allows you to efficiently retrieve entities from your database by:

  • Providing a list of IDs (e.g., int, Guid, string, etc.)
  • Providing a list of entities and using their primary key or a custom key expression

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Bulk read by list of IDs
var list1 = context.Customers.BulkRead(ids);

// Bulk read by custom key
var list2 = context.Customers.BulkRead(list, x => new { x.Email, x.PhoneNumber });

// Bulk read async versions
var list3 = await context.Customers.BulkReadAsync(ids);

Where Bulk Contains β€” For EF Core with Entity Framework Extensions

The EF Core WhereBulkContains method from Entity Framework Extensions allows you to filter your database table to return only the entities that match the values in a list.

It supports almost any kind of data source, including:

  • Basic types like List<int> or List<Guid>
  • Entity types like List<Customer>
  • Anonymous types
  • Lists of ExpandoObject

Unlike BulkRead, the WhereBulkContains method is deferred, meaning it doesn't execute immediately. It simply builds the query. If you want to retrieve the results, just call .ToList() (which is what BulkRead does under the hood).

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Filter by list of IDs
var list1 = context.Customers.WhereBulkContains(ids).ToList();

// Filter by custom key
var list2 = context.Customers.WhereBulkContains(list, x => new { x.Email, x.PhoneNumber });

// Async version
var list3 = await context.Customers.WhereBulkContains(ids).ToListAsync();

Where Bulk Not Contains β€” For EF Core with Entity Framework Extensions

The EF Core WhereBulkNotContains method from Entity Framework Extensions works just like WhereBulkContains, but in reverse. It returns all entities from the database that do not match the values in the provided list.

You can use it with:

  • Basic types like List<int> or List<Guid>
  • Entity types like List<Customer>
  • Anonymous types
  • Lists of ExpandoObject

Like WhereBulkContains, WhereBulkNotContains is a deferred method β€” it builds the query but doesn't execute it until you call something like .ToList(). In contrast, BulkRead is an immediate method that internally uses WhereBulkContains().ToList().

πŸ’‘ Example Usage

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Filter to get database records NOT in the list of IDs
var list1 = context.Customers.WhereBulkNotContains(ids).ToList();

// Filter by custom key
var list2 = context.Customers.WhereBulkNotContains(list, x => new { x.Email, x.PhoneNumber });

// Async version
var list3 = await context.Customers.WhereBulkNotContains(ids).ToListAsync();

Conclusion

Using Bulk Extensions in EF Core with Entity Framework Extensions is one of the most effective ways to boost the performance and memory efficiency of your application β€” especially in its most critical areas.

Whether you're inserting, updating, deleting, or reading large amounts of data, these methods are built to do it fast and reliably. Plus, with hundreds of customization options, you can tailor each bulk operation to fit your exact needs.

Every developer working with EF Core should try Entity Framework Extensions at least once β€” you'll instantly see the difference.


Last updated: 2025-07-31
Author: