Data layer and SQL
DbContext, connection pooling and request scope
Why there is one DbContext per request, and why database connections are reused.
Understand the concept
A DbContext is EF Core’s ‘unit of work’: it runs queries, tracks changes on loaded objects and writes them all to the database when SaveChanges is called. It is lightweight but not thread-safe, and tracked objects accumulate over time. A new DbContext is therefore created for each HTTP request and released when the request ends; AddDbContext does this automatically with a scoped lifetime.
Opening a database connection is expensive: network handshake, authentication, session setup. The ADO.NET connection pool does not really close closed connections; it returns them to the pool, and the next request with the same connection string gets a ready connection. DbContext holds a connection only while a query runs and returns it immediately.
The pool has a limit (100 by default in the SQL Server client). Operations that hold connections for long, readers left open or very long transactions exhaust the pool, and new requests wait with ‘Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool’.
Wrong lifetimes and leaked connections stop an app suddenly under load.
Keeping a DbContext in a static field or a singleton service.
One topic. Three levels of depth.
builder.Services.AddDbContext<PortfolioDbContext>(o =>
o.UseSqlServer(builder.Configuration.GetConnectionString("Portfolio")));DbContext is registered as scoped; each request gets its own instance.
This page connects to no real server or database. Code samples are illustrative for .NET 8, Next.js and SQL Server; timings are example values in the simulation, not measurements. Try samples only in your own development environment; never share real connection strings, tokens or passwords.
Try it yourself first.
At peak times requests wait 15 seconds and fail with a ‘connection pool’ timeout, yet SQL Server CPU is at 10%. What do you look at first?
Show the solution and explanation
Bağlantıyı uzun süre tutan kodlara:
- uzun transaction’lar veya transaction içinde dış servis çağrısı
- dispose edilmeyen DbContext/SqlConnection/DataReader
- senkron bekleme (.Result) nedeniyle tıkanan iş parçacıkları
SQL Server boşta, ama bağlantılar uygulamada kilitli kalıyor.The problem is not database capacity but connections not returning to the pool.