efcore: ObjectDisposedException on retrieval of a pooled DbContext

EF Core version: 6.0.0-rc1 Database provider: any Target framework: .NET 6.0 Operating system: any IDE: any

https://github.com/dotnet/efcore/blob/release/6.0/src/EFCore/DbContext.cs#L902 - looks like _disposed field should be set to false here instead (and in the *Async version of the same method). The existing code causes any DbContext that was returned back to the pool to throw ObjectDisposedException on attempt to rent it again.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 16 (9 by maintainers)

Commits related to this issue

Most upvoted comments

@roji Race condition:

Context is disposed:

        public virtual void Dispose()
        {
            var leaseActive = _lease.IsActive;
            var contextDisposed = leaseActive && _lease.ContextDisposed();

            if (DisposeSync(leaseActive, contextDisposed))
            {
                _serviceScope?.Dispose();
            }
        }

Calls _lease.ContextDisposed();

        public bool ContextDisposed()
        {
            if (_standalone)
            {
                Release();

                return true;
            }

            return false;
        }

Context is now back in the pool. Back to Dispose method, DisposeSync is called:

        private bool DisposeSync(bool leaseActive, bool contextDisposed)
        {
            if (leaseActive)
            {
                if (contextDisposed)
                {
                    _disposed = true;
                    _lease = DbContextLease.InactiveLease;
                }
            }
...

Context is marked as disposed and lease is deactivated. But by this time the context may already have been pulled from the pool again, so we deactivate a context that is in use.

@roji Can you prepare a PR cherry-picking this to 5.0.x?

FYI I don’t think this bug exists in 3.1 - it doesn’t seem like the DbContext is mutated in any way after being returned to the pool (code).

@roji , @ajcvickers , huge thanks - I also wanted to post a working example, but just got back to this & was pleasantly surprised!