Decrement active contexts count after a pooled DbContext instance is torn-down#38554
Decrement active contexts count after a pooled DbContext instance is torn-down#38554AndriySvyryd wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses an instrumentation bug in EF Core’s microsoft.entityframeworkcore.active_dbcontexts metric when using DbContextPool: contexts created during pool overflow were not decrementing the active count after they were fully torn down, causing the metric to monotonically increase (Fixes #38538).
Changes:
- Add metric-focused tests to validate that active DbContext counts decrement when an overflowed pooled context is torn down.
- Add a pooling regression test asserting that re-leasing a fully torn-down pooled context throws rather than dereferencing a cleared configuration snapshot.
- Update
DbContextpooling/disposal internals to handle “fully torn down” pooled contexts more explicitly.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| test/EFCore.Tests/Infrastructure/EntityFrameworkMetricsTest.cs | Adds tests covering active_dbcontexts behavior for pooled overflow tear-down scenarios (factory + scoped pooling). |
| test/EFCore.SqlServer.FunctionalTests/DbContextPoolingTest.cs | Adds a regression test for attempting to set a lease on a fully torn-down pooled context. |
| src/EFCore/DbContext.cs | Adjusts lease-setting and disposal logic to account for fully torn-down pooled contexts and metrics. |
Comments suppressed due to low confidence (1)
src/EFCore/DbContext.cs:1136
- The new dispose guard
else if (!_disposed || _configurationSnapshot != null)will run the full teardown path (including clearing_configurationSnapshot) even when the context has already been disposed but is just sitting idle in the pool (it retains a non-null_configurationSnapshot). That makes a secondDispose()on a pooled context (which is expected to be an idempotent no-op) fully tear the context down while it remains enqueued in the pool, corrupting the pool and causing subsequent rentals (which callSetLease) to start throwingObjectDisposedException.
Consider keeping the idempotency guard here (only run teardown when transitioning to disposed), and instead make the pool’s teardown path explicitly trigger teardown+metrics (e.g., have IDbContextPoolable.ClearLease() also mark the context as not-disposed so the following Dispose() performs teardown, or introduce a dedicated pool-only teardown method).
else if (!_disposed || _configurationSnapshot != null)
{
EntityFrameworkMetricsData.ReportDbContextDisposing();
_dbContextDependencies?.InfrastructureLogger.ContextDisposed(this);
Fixes #38538