Entity Framework DbContext instance being disposed when two different instances used as Task

I’m trying to run two queries in parallel, which then get loaded into a view.

I’m doing something like this:

Task<IEnumerable<MyClass>> someData;
Task<IEnumerable<MyOtherClass>> someOtherData;

using (MyContext ctx1 = new())
    someData = ctx1.MyClass.Where(x => x.ID == id);

using (MyContext ctx2 = new())
    someOtherData = ctx2.MyOtherClass.Where(x => x.ID == id);

await Task.WhenAll(someData, someOtherData);

//Do stuff with someData.Result, someOtherData.Result

However, I am getting an ObjectDisposedException.

I understand that DbContext is not thread-safe, but this should be creating and using two different instances… So how comes they appear to be using the same one (and thus it is getting disposed before/during the second call)?

The DbContext looks like this:

public partial class MyContext : DbContext
    public MyContext ()

    public MyContext(DbContextOptions<MyContext> options)
        : base(options)
    //Plus OnConfiguring, OnModelCreating, etc

>Solution :

First of all, your code will not compile at all because the Where method has an IQueryablye output and not a Task type.
Assuming that we correct your code. Your problem goes back to the when you use Curly braces for scope, and practically, since your code is executed outside of those scopes, DbContext is no longer available.

Beginning with C# 8.0, the using keyword can be used as an attribute in the variable declarations of disposable objects (Reference). The semantics is as you would expect — the objects are auto-disposed at the end of the scope.

The following code is modified from your code and the best practice is to use Using Statement

await using MyContext ctx1 = new();
await using MyContext ctx2 = new();

var someData = ctx1.MyClass.Where(x => x.ID == id).ToListAsync();

var someOtherData = ctx2.MyOtherClass.Where(x => x.ID == id).ToListAsync();;

await Task.WhenAll(someData, someOtherData);

Leave a Reply