ChilliCream / graphql-workshop

Getting started with GraphQL on ASP.NET Core and Hot Chocolate - Workshop
465 stars 199 forks source link

Session #6 "GetSessionsContaining2InTitle" "Cannot access a disposed context instance." in v12.4.1 #85

Closed Dwipraj closed 1 month ago

Dwipraj commented 2 years ago

After upgrading Session #6's HotChocolate.AspNetCore and HotChocolate.Data to version 12.4.1 running

   query GetSessionsContaining2InTitle {
     sessions(where: { title: { contains: "2" } }) {
       nodes {
         title
       }
     }
   }

gives error

{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "sessions"
      ],
      "extensions": {
        "message": "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.\r\nObject name: 'ApplicationDbContext'.",
        "stackTrace": "   at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()\r\n   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()\r\n   at Microsoft.EntityFrameworkCore.DbContext.get_Model()\r\n   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()\r\n   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.CheckState()\r\n   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()\r\n   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()\r\n   at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)\r\n   at HotChocolate.Data.Filters.Expressions.QueryableFilterProvider.<>c__DisplayClass11_0`1.<CreateApplicatorAsync>b__0(IResolverContext context, Object input)\r\n   at HotChocolate.Data.Filters.Expressions.QueryableFilterProvider.<>c__DisplayClass10_0`1.<<CreateExecutor>g__ExecuteAsync|1>d.MoveNext()\r\n--- End of stack trace from previous location ---\r\n   at HotChocolate.Types.Pagination.PagingMiddleware.InvokeAsync(IMiddlewareContext context)\r\n   at HotChocolate.Utilities.MiddlewareCompiler`1.ExpressionHelper.AwaitTaskHelper(Task task)\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)"
      }
    }
  ],
  "data": {
    "sessions": null
  }
}

But, removing disposeAsync: (s, c) => c.DisposeAsync() argument from descriptor.UseScopedService in ObjectFieldDescriptorExtensions class's UseDbContext method resolved the error.

public static class ObjectFieldDescriptorExtensions
    {
        public static IObjectFieldDescriptor UseDbContext<TDbContext>(
            this IObjectFieldDescriptor descriptor)
            where TDbContext : DbContext
        {
            return descriptor.UseScopedService<TDbContext>(
                create: s => s.GetRequiredService<IDbContextFactory<TDbContext>>().CreateDbContext());
        }

        public static IObjectFieldDescriptor UseUpperCase(
            this IObjectFieldDescriptor descriptor)
        {
            return descriptor.Use(next => async context =>
            {
                await next(context);

                if (context.Result is string s)
                {
                    context.Result = s.ToUpperInvariant();
                }
            });
        }
    }

So, my question is that Is explicitly adding disposeAsync attribute necessary for disposing of the DbContext?

EncodedViking commented 2 years ago

I'm experiencing this same behavior. Any word on it? It exists in version 12.5.0 as well as 12.4.1.

zachbugay commented 2 years ago

I am still experiencing this issue on 12.7.0 as well. It would be nice to have an update around this.

albx commented 2 years ago

Same issue on tracks query mentioned in step 6 (https://github.com/ChilliCream/graphql-workshop/blob/master/docs/6-adding-complex-filter-capabilities.md#add-paging-to-your-lists) using v 12.7.0.

For me too removing the disposeAsync in the UseDbContext middleware solves the issue. Any updates on what is the best way to approach?

Thanks

bardhyliis commented 2 years ago

Same issue on tracks query mentioned in step 6 (https://github.com/ChilliCream/graphql-workshop/blob/master/docs/6-adding-complex-filter-capabilities.md#add-paging-to-your-lists) using v 12.7.0.

For me too removing the disposeAsync in the UseDbContext middleware solves the issue. Any updates on what is the best way to approach?

Thanks

You got any other solution except removing disposeAsync?

JohanHeyvaert commented 2 years ago

Same problem here. Removing disposeAsync "fixes" the problem so thanks for that workaround.

Earlier I tried to fix it by using RegisterDbContext() from HotChocolate.Data.EntityFramework (cf. article https://chillicream.com/docs/hotchocolate/integrations/entity-framework) but so far I didn't manage to get it up and running. I'm not sure what to do in the type resolvers and the dataloaders. Also, do we still need to use UseApplicationDbContextAttribute? It would be great if the workshop could be updated using this technique!

esausilva commented 1 year ago

I know this is an old post, but removing [UseApplicationDbContext] from the GetTracks method works

glen-84 commented 1 month ago

I'm closing this issue as outdated, as we have an updated workshop on the main branch, for Hot Chocolate 14.