EF Core Batch Delete — Complete Guide
In this tutorial, you'll learn about EF Core Batch Delete. We cover key concepts, practical examples, and best practices.
You need to delete all expired orders. Without batch operations, you load every order, add each to the deletion tracker, and call SaveChanges — sending individual DELETE statements. EF Core batch delete (EF Core 7+) generates a single SQL DELETE.
Wrong
var expired = await db.Orders
.Where(o => o.ExpiryDate < DateTime.UtcNow)
.ToListAsync();
db.Orders.RemoveRange(expired);
await db.SaveChangesAsync();
Output: SELECT * FROM Orders WHERE ExpiryDate < @now followed by N individual DELETE statements. Memory grows with the number of deleted orders.
Right (EF Core 7+)
await db.Orders
.Where(o => o.ExpiryDate < DateTime.UtcNow)
.ExecuteDeleteAsync();
Output: Single SQL: DELETE FROM Orders WHERE ExpiryDate < '2026-06-24'. No data loaded into memory.
ExecuteDeleteAsync works with any IQueryable, including navigation properties:
await db.Products
.Where(p => !p.OrderDetails.Any())
.ExecuteDeleteAsync();
// DELETE FROM Products WHERE Id NOT IN (SELECT ProductId FROM OrderDetails)
Prevention
- Use
ExecuteDeleteAsyncfor bulk deletes in EF Core 7+. - Use
ExecuteUpdateAsyncfor bulk updates. - Compose
Whereclauses for targeted deletion. - Use with navigation properties for complex filter conditions.
- Handle cascade delete constraints — the database enforces them.
- Use transactions to roll back accidental bulk deletes.
- Test with a SELECT first to verify the WHERE clause matches expected rows.
Common Mistakes with core batch delete
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
- Misunderstanding that
Stringis[Char]with poor performance for large text operations - Using
foldlinstead offoldl'causing stack overflow on large lists
These mistakes appear frequently in real-world EF code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Batch delete operations power DodaTech's data retention and cleanup jobs. For more EF Core, visit DodaTech.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro