3

ConfigureServices

services.AddSingleton<IServiceProvider>(c => new FuncServiceProvider(type => c.GetRequiredService(type)));
services.AddDbContext<Context>(options => options.UseSqlServer(configuration.GetConnectionString("Default")));

services.AddSingleton<Query>();
services.AddSingleton<Schema>();

services.AddGraphQL();

Configure

app.UseGraphQL<Schema>();

Query

    public class Query : ObjectGraphType
    {
        public Query(IServiceProvider resolver)
        {
            var db = resolver.GetRequiredService<Context>();

            Name = "query";
            Field<ListGraphType<Types.Note>>("notes", resolve: _ => db.Notes.AsAsyncEnumerable());
        }
    }

executing the GraphQL endpoint results in the following exception

System.InvalidOperationException: Cannot resolve scoped service 'Models.Database.Context' from root provider.

some more details.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
420skun
  • 99
  • 4
  • Why are `Query` and `Schema` Singletons? – Nkosi Oct 22 '19 at 17:34
  • I deduced it from [link](https://github.com/graphql-dotnet/examples/blob/8d5b7544006902f45b818010585b1ffa86ef446b/src/AspNetCoreCustom/Example/Startup.cs#L16-L34). AddScoped works but doesn't it perform worse? – 420skun Oct 22 '19 at 17:43
  • That example used singletons because it is being used in a middlewares, which are basically singletons. – Nkosi Oct 22 '19 at 17:47

1 Answers1

2

Query and Schema should be scoped as well if it wants to take advantage of using a DbContext which is added as scoped by default.

services.AddDbContext<Context>(options => options.UseSqlServer(configuration.GetConnectionString("Default")));

services.AddScoped<Query>();
services.AddScoped<Schema>();

services.AddGraphQL()
    .AddGraphTypes(ServiceLifetime.Scoped);;

And the Context should be explicitly injected

public class Query : ObjectGraphType {
    public Query(Context db) {
        Name = "query";
        Field<ListGraphType<Types.Note>>("notes", resolve: _ => db.Notes.AsAsyncEnumerable());
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • You may wish to consider [this](https://stackoverflow.com/questions/58873249) and [this](https://codereview.stackexchange.com/a/238506/219835). If you use that same `db` in multiple Fields, you're going to get an exception because resolvers are executed in parallel and EFC's `DbContext` doesn't do multi-threaded queries. – Granger Mar 11 '20 at 23:04