Entity Framework Plus EF Core ExecuteDelete
EF Core 7 introduced ExecuteDelete, a built-in method that performs a delete directly in the database without loading entities into memory.
This method covers most scenarios that previously required our DeleteFromQuery method, which our company supported for many years. Today, we generally recommend using the built-in ExecuteDelete method whenever possible.
However, while ExecuteDelete covers most scenarios, some real-world situations can still benefit from additional features. For this reason, our library provides extensions that build on top of ExecuteDelete:
- Basic ExecuteDelete - Delete rows directly in the database without loading entities into memory.
- Using ExecuteDelete with Batch - Delete rows in batches to better control transaction log growth and large delete operations.
- Using ExecuteDelete with Future Action - Register delete operations and execute them later in a centralized location.
- Using ExecuteDelete with Hint - Add SQL query hints when you need more control over how the database executes the delete operation.
ExecuteDelete Example
Basic ExecuteDelete
The ExecuteDelete method deletes all rows that match the query directly in the database without loading entities into memory.
var rowsAffected = context.Customers
.Where(x => x.IsDeleted)
.ExecuteDelete();
The method returns the number of rows affected by the operation.
Benefits:
- Included directly in EF Core 7 and later
- Deletes rows without loading entities into memory
- Executes a single SQL statement
- Returns the number of rows affected
This article focuses on additional features built on top of ExecuteDelete. For complete documentation about the built-in EF Core method, see ExecuteDelete.
Using ExecuteDelete with Batch
A major limitation of ExecuteDelete is that it deletes all matching rows in a single operation. While this works well for smaller datasets, it can become problematic when deleting millions of rows. In such cases, the transaction log can grow very quickly, increasing I/O, extending lock durations, and significantly impacting performance.
To solve this issue, our library provides ExecuteDeleteBatch and ExecuteDeleteBatchAsync. These methods take a batch size as a parameter and repeatedly execute ExecuteDelete until no more rows match the query. The method returns the total number of rows deleted across all batches.
// @nuget: Z.EntityFramework.Plus.EFCore using Z.EntityFramework.Plus; var rowsAffected = context.Customers .Where(x => x.IsDeleted) .ExecuteDeleteBatch(25000);
By processing rows in smaller batches, you can better control transaction log growth and avoid the performance issues often associated with very large delete operations.
Benefits:
- Deletes rows in batches instead of all at once
- Returns the total number of rows deleted across all batches
- Helps control transaction log growth
- Reduces the risk of long-running delete operations
- Automatically participates in the current transaction when one is already in progress
- Otherwise, executes all batches within its own transaction to ensure consistency
Using ExecuteDelete with Future Action
You can combine ExecuteDelete with Future Action when you want to register one or more delete operations and execute them later in a single place.
This is especially useful when your ExecuteDelete calls are located in multiple repositories. Each repository can register its own delete operation without executing it immediately, and your application can decide later when all registered actions should be executed.
// @nuget: Z.EntityFramework.Plus.EFCore using Z.EntityFramework.Plus; context.FutureAction(x => x.Customers .Where(c => c.IsDeleted) .ExecuteDelete()); context.FutureAction(x => x.Orders .Where(o => o.IsArchived) .ExecuteDelete()); // Execute all registered actions context.ExecuteFutureAction();
When ExecuteFutureAction() is called, all registered actions are executed in the order they were added to the queue.
Benefits:
- Defers execution until you decide to execute it
- Centralizes execution when delete operations are registered from multiple repositories
- Keeps repository logic separated while keeping execution controlled in one place
- Can execute multiple delete operations together
- Supports transactional execution with
ExecuteFutureAction(true)orExecuteFutureActionAsync(true)
Using ExecuteDelete with Hint
Sometimes you need to control how the database executes a delete operation. For example, you might want to apply SQL query hints to influence locking behavior or improve performance for a specific scenario.
Our library lets you apply query hints to ExecuteDelete by using the WithHint extension method before calling ExecuteDelete or ExecuteDeleteAsync.
// @nuget: Z.EntityFramework.Plus.EFCore using Z.EntityFramework.Plus; var rowsAffected = context.Customers .Where(x => x.IsDeleted) .WithHint(SqlServerTableHintFlags.TABLOCK) .ExecuteDelete();
Query hints are provider-specific and are only applied when supported by the current database provider.
Benefits:
- Applies SQL query hints to
ExecuteDelete - Helps control locking behavior for delete operations
- Can improve performance in specific scenarios
- Uses the same API as other query hint features provided by the library
- Works seamlessly with
ExecuteDeleteandExecuteDeleteAsync
Summary
In this article, you learned how to use EF Core's ExecuteDelete method together with additional features provided by Entity Framework Plus.
While we generally recommend using the built-in ExecuteDelete method, our library offers extensions for scenarios where you need more control:
- Use
ExecuteDeleteBatchandExecuteDeleteBatchAsyncto delete rows in batches, helping control transaction log growth and improve performance when working with very large tables. - Use
FutureActionto register one or more delete operations and execute them later in a centralized location, which is especially useful when working with multiple repositories. - Use
WithHintto apply provider-specific query hints to the generated delete command.
These features build on top of ExecuteDelete and help address common challenges encountered in large applications and production environments.
ZZZ Projects