September 16 2025
// Program.cs builder.Services.AddDbContext<AppDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("Default")));
builder.Services.AddDbContextFactory<AppDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("Default")));
public sealed class ReportService(IDbContextFactory<AppDbContext> factory) { public async Task<IReadOnlyList<OrderDto>> GetAsync(CancellationToken ct) { await using var db = await factory.CreateDbContextAsync(ct); return await db.Orders .Where(o => o.Status == OrderStatus.Completed) .Select(o => new OrderDto(o.Id, o.Total)) .ToListAsync(ct); } }
builder.Services.AddDbContextPool<AppDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("Default")));
app.MapGet("/orders/{id:int}", async (int id, AppDbContext db, CancellationToken ct) => { var order = await db.Orders.FindAsync([id], ct); return order is null ? Results.NotFound() : Results.Ok(order); });
public sealed class CleanupService(IServiceScopeFactory scopes, ILogger<CleanupService> log) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { using var scope = scopes.CreateScope(); var db = scope.ServiceProvider.GetRequiredService<AppDbContext>(); // One short-lived unit of work var cutoff = DateTime.UtcNow.AddDays(-30); db.RemoveRange(db.AuditLogs.Where(x => x.CreatedAt < cutoff)); await db.SaveChangesAsync(stoppingToken); await Task.Delay(TimeSpan.FromHours(6), stoppingToken); } } }
public sealed class CleanupService(IDbContextFactory<AppDbContext> factory, ILogger<CleanupService> log) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { await using var db = await factory.CreateDbContextAsync(ct); // same cleanup logic … await Task.Delay(TimeSpan.FromHours(6), ct); } } }
public sealed class PricingCache(IDbContextFactory<AppDbContext> factory, IMemoryCache cache) { public async Task<decimal> GetPriceAsync(int productId, CancellationToken ct) { if (cache.TryGetValue(productId, out decimal price)) return price; await using var db = await factory.CreateDbContextAsync(ct); price = await db.Products .Where(p => p.Id == productId) .Select(p => p.Price) .FirstAsync(ct); cache.Set(productId, price, TimeSpan.FromMinutes(10)); return price; } }
builder.Services.AddDbContextPool<AppDbContext>(o => { o.UseNpgsql(builder.Configuration.GetConnectionString("Default")); // Keep options stateless; avoid per-request mutable state });
1. Design Patterns that Deliver
This isn’t just another design patterns book. Dive into real-world examples and practical solutions to real problems in real applications.Check out it here.
Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.
Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.
Join 18,000+ subscribers to improve your .NET Knowledge.
Subscribe to the TheCodeMan.net and be among the 18,000+ subscribers gaining practical tips and resources to enhance your .NET expertise.