ð Problem Before EF7 (EF6 and below):
When you wanted to update multiple records:
-
You had to load the data into memory.
-
Loop through and modify each entity.
-
Call
SaveChangesAsync()
which sends multiple UPDATE statements to the database.
ð§ą Traditional Way (Before EF7)
// EF6 or EF Core < 7
var productIdsToUpdate = new List<int> { 1, 2, 3 };
var products = await dbContext.Products
.Where(p => productIdsToUpdate.Contains(p.Id))
.ToListAsync();
foreach (var product in products)
{
product.IsActive = false; // Mark as inactive
}
await dbContext.SaveChangesAsync(); // Multiple UPDATEs under the hood
â Drawback: All records are loaded into memory and updated one by one â this is slow and memory-intensive for large datasets.
â New & Efficient Way in EF Core 7+
ExecuteUpdateAsync
to the rescue!
// EF Core 7+
var productIdsToUpdate = new List<int> { 1, 2, 3 };
await dbContext.Products
.Where(p => productIdsToUpdate.Contains(p.Id))
.ExecuteUpdateAsync(setters => setters
.SetProperty(p => p.IsActive, false)
);
â Benefit: Generates a single SQL UPDATE statement like:
UPDATE Products
SET IsActive = 0
WHERE Id IN (1, 2, 3)
ðĨ Why it matters:
-
No need to load data into memory.
-
No need for EF change tracking.
-
Fast, lightweight, and scales well.
ð Use Cases
-
Bulk status updates (e.g., mark records inactive/archived)
-
Flag updates (e.g., IsDeleted, IsSynced)
-
Audit field updates (e.g., UpdatedAt, UpdatedBy)
â ïļ Requirements
-
ExecuteUpdateAsync
is available only in EF Core 7+. -
Works only with LINQ queries directly targeting a single entity/table (no includes or complex projections).