Understanding the importance of async/await for database operations
Thread blocked during execution
// ❌ BAD - Synchronous blocking call
var products = _context.DemoProducts
.Where(p => p.IsActive)
.OrderBy(p => p.Name)
.Take(1000)
.ToList(); // Blocks thread!
// Thread is blocked waiting for database
Thread freed during I/O
// ✅ GOOD - Asynchronous non-blocking call
var products = await _context.DemoProducts
.Where(p => p.IsActive)
.OrderBy(p => p.Name)
.Take(1000)
.ToListAsync(); // Returns thread to pool
// Thread available for other work
Using async/await for database operations (measured on response time)
// Get single entity
var product = await _context.Products
.FirstOrDefaultAsync(p => p.Id == id);
// Get list
var products = await _context.Products
.Where(p => p.IsActive)
.ToListAsync();
// Check existence
bool exists = await _context.Products
.AnyAsync(p => p.SKU == sku);
// Count
int count = await _context.Products
.CountAsync(p => p.Category == "Electronics");
// Get specific value
decimal maxPrice = await _context.Products
.MaxAsync(p => p.Price);
// Add
_context.Products.Add(newProduct);
await _context.SaveChangesAsync();
// Update
var product = await _context.Products
.FindAsync(id);
product.Price = 99.99m;
await _context.SaveChangesAsync();
// Delete
var product = await _context.Products
.FindAsync(id);
_context.Products.Remove(product);
await _context.SaveChangesAsync();
// Bulk operations
await _context.Products
.Where(p => p.IsActive == false)
.ExecuteDeleteAsync();
| Metric | Synchronous | Asynchronous | Improvement |
|---|---|---|---|
| Thread Pool Size | 100 threads | 100 threads | - |
| Avg Query Time | 50ms | 50ms | Same |
| Thread Blocking Time | 50ms (blocked) | ~0ms (freed) | 100% |
| Max Concurrent Requests | ~100 | ~10,000+ | 100x |
| Thread Starvation Risk | High | Low | Much Better |
| CPU Utilization | Low (waiting) | High (productive) | Better |
async/await for ALL database operations
ToListAsync(), FirstAsync(), etc.
SaveChangesAsync() for updates
async Task<IActionResult>
await keyword - don't block with .Result
.Result or .Wait() - causes deadlocks
ToList(), First())
await keyword (creates fire-and-forget)
async void (except event handlers)
// DEADLOCK in ASP.NET!
public IActionResult GetProducts()
{
// Blocks thread waiting for async operation
var products = _context.Products
.ToListAsync()
.Result; // DEADLOCK!
return View(products);
}
// ✅ CORRECT
public async Task<IActionResult> GetProducts()
{
var products = await _context.Products
.ToListAsync();
return View(products);
}
// BAD - Can't catch exceptions
public async void LoadData()
{
var products = await _context.Products
.ToListAsync();
// Exception here is lost!
}
// ✅ CORRECT
public async Task LoadDataAsync()
{
var products = await _context.Products
.ToListAsync();
// Exceptions properly propagated
}