Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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);

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading