Handling Transactions in EF Core: SaveChanges vs Explicit Transactions
Your application works perfectly in development, but in production, you’re seeing partial data updates and mysterious consistency issues. The problem isn’t your business logic, it’s how you’re handling transactions.
EF Core gives you two ways to manage transactions: the automatic approach with SaveChanges, and explicit transaction control. Each has its place, but using the wrong one can cost you data integrity or performance.
How EF Core SaveChanges Handles Transactions
SaveChanges automatically wraps all your changes in a single database transaction. This means multiple entity operations either all succeed or all fail together:
// This entire operation is one transaction
using var context = new OrderContext();
var customer = new Customer { Name = "John Doe" };
var order = new Order { CustomerId = customer.Id, Total = 100.50m };
var orderItem = new OrderItem { OrderId = order.Id, ProductId = 1 };
context.Customers.Add(customer);
context.Orders.Add(order);
context.OrderItems.Add(orderItem);
await context.SaveChangesAsync(); // All or nothing
If any part fails, everything rolls back. Your database stays consistent without any extra code.
When SaveChanges Transactions Aren’t Enough
Multiple SaveChanges Calls
The automatic transaction only covers a single SaveChanges call. If your business logic requires multiple save operations, you need explicit control:
// Problem: Two separate transactions
public async Task ProcessOrderAsync(Order …