question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AddDbContextPool in asp.net core System.InvalidOperationException

See original GitHub issue

I’m using db context pooling in a Asp.Net core MVC application. When I launch multiple simultaneous requests I get an error :

Exception message: System.InvalidOperationException occurred in Microsoft.EntityFramework.Core.dll
A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.

or 
Exception message: System.ObjectDisposedException: 'Cannot access a disposed object.

code;
IQueryable<TEntity> query = DbSet;
            if (filter != null)
                query = query.Where(filter); // exception occurs here

Maybe I’m not using DbContext pooling the right way…

Steps to reproduce

I launch mutiple requests in browser to the same web api controller method, which retrieves some data from the database.

 // Dependency injection is configured in Startup as follows
    services.AddScoped<IMyDbContext>(provider => provider.GetService<MyDbContext>());

// if I use service.AddScoped<IMyDbContext,MyDbContext>();
//  I get the impression db context pooling is not working, 
//  but I don't get the exception message either.

// db context pooling in Startup class
   services.AddDbContextPool<MyDbContext>(options =>
            {
                string connectionString = Configuration.GetConnectionString("MyConnection");
                options.UseSqlServer(connectionString);
            },10);

Further technical details

EF Core version:Microsoft.EntityFrameworkCore.SqlServer" Version=“2.0.0” Database Provider: Microsoft.EntityFrameworkCore.SqlServer Operating system: Win10 IDE: Visual Studio 2017

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:12 (9 by maintainers)

github_iconTop GitHub Comments

3reactions
ajcvickerscommented, Sep 14, 2017

@rekna1 I was actually able to reproduce this in a console application, so no need to dig further.

Note for triage: Works fine when AddDbContextPool is replaced by AddDbContext

public interface IMyDbContext
{
    DbSet<Foo> Foos { get; set; }
}

public class MyDbContext : DbContext, IMyDbContext
{
    public MyDbContext(DbContextOptions<MyDbContext> options) 
        : base(options)
    {
    }

    public DbSet<Foo> Foos { get; set; }
}

public class Foo
{
    public int Id { get; set; }
}

public class Program
{
    public static void Main()
    {
        var services = new ServiceCollection()
            .AddScoped<IMyDbContext>(provider => provider.GetService<MyDbContext>())
            .AddDbContextPool<MyDbContext>(options =>
            {
                options.UseSqlServer(
                    @"Server=(localdb)\mssqllocaldb;Database=Test;Trusted_Connection=True;ConnectRetryCount=0");
            })
            .BuildServiceProvider();

        using (var scope = services.CreateScope())
        {
            var context = (DbContext)scope.ServiceProvider.GetService<IMyDbContext>();
            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();
        }

        Parallel.For(0, 100, s =>
        {
            using (var scope = services.CreateScope())
            {
                var context = scope.ServiceProvider.GetService<IMyDbContext>();

                Console.WriteLine("Using " + context.GetHashCode());
                context.Foos.Add(new Foo());
                ((DbContext) context).SaveChanges();
                var _ = context.Foos.ToList();
            }
        });
    }
}
2reactions
ajcvickerscommented, Sep 18, 2017

@anpete Yes, but I think you knew that by now. With regard to getting disposed twice, the IDisposable interface explicitly allows that, so I think it’s something we have to handle. From MSDN:

If an object’s Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The DbContext of type cannot be pooled because it does ...
I am trying to upgrade our current .Net Core application from 1.1 to 2.0 and am getting this runtime error: "The DbContext of...
Read more >
DbContext Lifetime, Configuration, and Initialization
An InvalidOperationException thrown by EF Core code can put the context into an unrecoverable state. Such exceptions indicate a program error ...
Read more >
Subtle breaking change when adding DbContextPool ...
NET Core 3.1 to .NET 6.0, I stumbled across a very subtle breaking changing when using the AddDbContextPool() feature of EF Core.
Read more >
Best Practices in Using the DbContext in EF Core
In Entity Framework Core (also called EF Core), a Db context is an object that coordinates queries, updates, and deletes against your database....
Read more >
DBContext- A second operation started on this context ...
Issue solution in EF Core error for ASP.NET Core and .NET Core for error - A second operation started on this context before...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found