You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

启用GraphQL的API出现作用域仓储无法解析的DI错误

GraphQL依赖注入错误:无法解析作用域服务

我使用GraphiQL访问GraphQL API(访问地址:https://localhost:7271/ui/graphiql)时,遇到如下错误:

无法从根提供程序解析'MyApp.Api.AppQuery',因为它需要作用域服务'MyApp.Data.Content.Repositories.Interfaces.INodeRepository'。

错误发生在AppSchema的构造函数中:

public AppSchema(IServiceProvider provider) : base(provider)
{
    Query = provider.GetRequiredService<AppQuery>();
    Mutation = provider.GetRequiredService<AppMutation>();
}

AppQuery的构造函数依赖INodeRepository:

public AppQuery(INodeRepository nodeRepository)
{
    _nodeRepository = nodeRepository;

    Name = nameof(AppQuery);

    Field<ListGraphType<NodeType>>("node")
        .Argument<StringGraphType>("id", "node id")
        .ResolveAsync(async context =>
            await _nodeRepository.GetByIdAsync(context.GetArgument<string>("id")));
}

我已在ConfigureDataServices中通过services.AddScoped<INodeRepository, NodeRepository>()注册了作用域的INodeRepository,但依赖注入仍无法找到它。以下是Main方法的完整代码:

public async static Task Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);
    var configurationBuilder = new ConfigurationBuilder()
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true)
        .AddEnvironmentVariables();
    var configuration = configurationBuilder.Build();
    builder.Services.AddSingleton<IConfigurationRoot>(configuration);
    // NodeRepository added by this:
    builder.Services.ConfigureDataServices(configuration);
    builder.Services.AddSingleton<ISchema, AppSchema>(services => 
        new AppSchema(new SelfActivatingServiceProvider(services)));
    builder.Services.AddGraphQL(b => b
        //.AddHttpMiddleware<ISchema>()
        //.AddUserContextBuilder(httpContext => new GraphQLUserContext { User = httpContext.User })
        .AddSystemTextJson()
        .AddSchema<AppSchema>()
        .AddGraphTypes(typeof(AppSchema).Assembly));
    builder.Services.AddControllers();
    var app = builder.Build();
    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.MapControllers();
    app.UseGraphQL<AppSchema>("/graphql");
    app.UseGraphQLGraphiQL();
    app.Run();
}

问题原因与修复方案

核心原因

你将AppSchema注册为单例服务,但在它的构造函数中直接解析了依赖作用域服务的AppQuery。单例服务的生命周期覆盖整个应用程序,而作用域服务是每个请求创建一次——根服务提供者(单例所在的容器)无法解析作用域服务,因为此时不存在请求作用域。

修复步骤

1. 调整AppSchema的注册生命周期

将AppSchema从单例改为作用域注册,让它随每个请求创建:

// 替换原来的AddSingleton注册代码
builder.Services.AddScoped<ISchema, AppSchema>();

2. 修改AppSchema构造函数,直接注入依赖

不要手动从IServiceProvider获取AppQuery和AppMutation,让DI容器自动注入:

public AppSchema(AppQuery query, AppMutation mutation) : base()
{
    Query = query;
    Mutation = mutation;
}

3. 注册AppQuery和AppMutation为作用域服务

如果未注册这两个类,需添加以下代码:

builder.Services.AddScoped<AppQuery>();
builder.Services.AddScoped<AppMutation>();

调整后的Main方法关键片段

// ... 其他配置代码
builder.Services.ConfigureDataServices(configuration);
// 新增Query和Mutation的作用域注册
builder.Services.AddScoped<AppQuery>();
builder.Services.AddScoped<AppMutation>();
// 修改Schema的注册为作用域
builder.Services.AddScoped<ISchema, AppSchema>();
builder.Services.AddGraphQL(b => b
    .AddSystemTextJson()
    .AddSchema<AppSchema>()
    .AddGraphTypes(typeof(AppSchema).Assembly));
// ... 其他配置代码

补充说明

作用域服务必须在请求作用域内解析,单例服务在应用启动时就已初始化,此时没有请求上下文,自然无法解析作用域依赖。通过让AppSchema也成为作用域服务,它会在每个请求时被创建,此时可以正常解析同为作用域的AppQuery、AppMutation,进而解析它们的依赖INodeRepository。

内容的提问来源于stack exchange,提问作者Jonas Arcangel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:57:41