dotnet data_error ai_generated true

System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.

ID: dotnet/ef-core-connection-timeout-pool-exhaustion

Also available as: JSON · Markdown · 中文
85%Fix Rate
85%Confidence
1Evidence
2023-06-15First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
Entity Framework Core 7.0 active
Entity Framework Core 8.0 active
Microsoft.Data.SqlClient 5.1.0 active

Root Cause

Connection pool exhaustion occurs when database connections are not properly disposed, causing all pooled connections to remain open and new requests to wait indefinitely.

generic

中文

连接池耗尽发生在数据库连接未正确释放时,导致所有池化连接保持打开状态,新请求无限期等待。

Official Documentation

https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling

Workarounds

  1. 85% success Ensure all DbContext instances are properly disposed by using 'using' statements or dependency injection scoped lifetime. For example: 'using (var context = new MyDbContext()) { ... }' or register as scoped in DI: 'services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Scoped)'.
    Ensure all DbContext instances are properly disposed by using 'using' statements or dependency injection scoped lifetime. For example: 'using (var context = new MyDbContext()) { ... }' or register as scoped in DI: 'services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Scoped)'.
  2. 80% success If using async operations, ensure every async call is awaited to avoid connection leaks from incomplete tasks. Use 'await using' for asynchronous disposal: 'await using var context = new MyDbContext();'
    If using async operations, ensure every async call is awaited to avoid connection leaks from incomplete tasks. Use 'await using' for asynchronous disposal: 'await using var context = new MyDbContext();'
  3. 70% success Temporarily increase Max Pool Size and Connection Timeout in the connection string as a short-term mitigation while fixing the root cause: 'Server=myServer;Database=myDB;Max Pool Size=200;Connection Timeout=30;'
    Temporarily increase Max Pool Size and Connection Timeout in the connection string as a short-term mitigation while fixing the root cause: 'Server=myServer;Database=myDB;Max Pool Size=200;Connection Timeout=30;'

中文步骤

  1. 确保所有 DbContext 实例通过使用 'using' 语句或依赖注入作用域生命周期正确释放。例如:'using (var context = new MyDbContext()) { ... }' 或在 DI 中注册为作用域:'services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Scoped)'。
  2. 如果使用异步操作,确保每个异步调用都被 await 以避免未完成任务导致连接泄漏。使用 'await using' 进行异步释放:'await using var context = new MyDbContext();'
  3. 临时增加连接字符串中的 Max Pool Size 和 Connection Timeout 作为短期缓解措施,同时修复根本原因:'Server=myServer;Database=myDB;Max Pool Size=200;Connection Timeout=30;'

Dead Ends

Common approaches that don't work:

  1. 75% fail

    Increasing Max Pool Size in the connection string only delays the issue; it does not fix the underlying leak.

  2. 90% fail

    Restarting the application temporarily clears the pool but connections will leak again if disposal is not fixed.

  3. 80% fail

    Adding retry logic without fixing disposal causes the same timeout to repeat, wasting resources and slowing response.