Cannot access to a disposed context instance

Cannot access to a disposed context instance


0

I’m using dotnet 6 with GraphQL 7. I’m having some issues only in one Field. The error appears only when the app is deployed in the cluster (kubernetes), but never in local. So it seems like the Dependency Injection is not working properly, here is the code of the query:

public class UserModulesProgressField : IGraphQueryField
{
    public void BindFields(ObjectGraphType parentObject)
    {

        parentObject.Field<ListGraphType<ModuleProgressType>, IEnumerable<ModuleProgress>>("userModulesProgress")
            .Description(GraphQLDescriptionConstants.ProtectedGraphQLDescription)
            .Resolve()
            .WithScope()
            .WithServices<IUnitOfWork, IGraphService>()
            .ResolveAsync(async (context, unitOfWork, graphService) =>
            {
                var user = await graphService.GetCurrentUser();
                var userId = user.Id.ToString();
                var modulesProgress = (await unitOfWork.ModulesProgressRepository.GetUserModulesProgressAsync(userId)).ToList();
                var bank = graphService.GetUserBank(user);
                var modules = await unitOfWork.ModuleRepository.GetBankModulesNoIncludeAsync(bank.Id);

                return modulesProgress.ToList();
            }
        );

    }
}`

The error is inside the GetBankModulesNoIncludeAsync(bank.Id), which contains the following:

    public async Task<IEnumerable<Module>> GetBankModulesNoIncludeAsync(int? bankId)
    {
        var dbModules = await _context.Modules
            .Where(e => e.BankModules.Any(b => b.BankId == bankId))
            .OrderBy(e => e.Rank)
            .ToListAsync();

        dbModules.ForEach(m => m?.OrderByRank());
        return dbModules;
    }`

The error I’m getting is:

[12:37:53 Error] Microsoft.EntityFrameworkCore.Query
An exception occurred while iterating over the results of a query for context type 'DTH.WebApp.Infrastructure.Data.ApplicationDbContext'.
System.ObjectDisposedException: Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'ApplicationDbContext'.
   at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_StateManager()
   at Microsoft.EntityFrameworkCore.Query.QueryContextDependencies.get_StateManager()
   at Microsoft.EntityFrameworkCore.Query.QueryContext.InitializeStateManager(Boolean standAlone)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass30_0`2.<<ExecuteAsync>b__0>d.MoveNext()

I tried (just for debugging) to add a delay with

await Task.Delay(2000); 

just after the var bank, and with that delay is working. But I don’t like to put random delays, I’d like to understand what is actually happening here! It’s weird because it is happening only on that query, and it should work because graphQL is taking care about Dependency Injection with:
.Resolve().WithScope().WithServices …

Any idea? What should I try next? I really don’t like putting random Delays (problably way less than 2s would work anyway, didn’t try yet because at every try I have to re-run the pipelines)

I tried to change syntax, tried to retrieve DB and services in another way, tried with conditions, nothing worked

Share
Improve this question

5

  • how did you register ApplicationDbContext?

    – Bagus Tesa

    Aug 7 at 13:31

  • I found the error.. damn so bad, I spent a whole day for that lol basically I had to add the await there: var bank = await graphService.GetUserBank(user); because it is an async call which use the UnitOfWork.. I'm adding the answer to the edits so that someone else would need

    – Raso

    Aug 7 at 13:44

  • What UnitOfWork? Post the relevant code. DbContext is a Unit-of-Work already. async/await doesn't have anything to do with UoW. The error is telling you that you tried to reuse a disposed DbContext after it was closed, probably because you tried to use the "repository-over-UoW" antipattern

    – Panagiotis Kanavos

    Aug 7 at 14:10


  • Assuming a best-case scenario, the "unit-of-work" class is only a very thin wrapper over DbContext and the "respositories" are just no-op wrappers over DbSets, and the entities have proper relations, you should be able to use only one query to load a user and the related modules. If User has a BankModules property, loading a User also gives access to the modules. There's no need for two separate queries

    – Panagiotis Kanavos

    Aug 7 at 14:14

  • Please post your answer in the answer box below. You are free to answer your own question.

    – Charlieface

    Aug 7 at 14:23

1 Answer
1

Reset to default


0

Looks like it was just missing an ‘await’ there:

var modulesProgress = (await unitOfWork.ModulesProgressRepository.GetUserModulesProgressAsync(userId)).ToList();
var bank = await graphService.GetUserBank(user);  // added await here
var modules = await unitOfWork.ModuleRepository.GetBankModulesNoIncludeAsync(bank.Id);

Share
Improve this answer



Not the answer you're looking for? Browse other questions tagged

or ask your own question.

Leave a Reply

Your email address will not be published. Required fields are marked *