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

如何通过IoC访问HotChocolate的QueryRequest以优化SQL查询性能

Better Ways to Access HotChocolate's IReadOnlyQueryRequest Without IHttpContextAccessor

Great question! Your current approach using HttpContext.Items works, but it ties your code tightly to ASP.NET Core's IHttpContextAccessor—which can make testing more cumbersome and couples your business/data logic to the web layer. HotChocolate provides native, cleaner alternatives to access the IReadOnlyQueryRequest across your application layers.

HotChocolate includes a built-in scoped context system designed to share data across the request execution pipeline without relying on HttpContext. Here's how to implement it:

Step 1: Store the Request in Scoped Context

Update your query request interceptor to use IScopedContextProvider instead of HttpContext.Items:

services.AddQueryRequestInterceptor(GraphQLRequestInterceptor);

// ...

private Task GraphQLRequestInterceptor(HttpContext context, IQueryRequestBuilder requestBuilder, CancellationToken cancellationToken)
{
    IReadOnlyQueryRequest request = requestBuilder.Create();
    // Get the scoped context provider from the request's service scope
    var scopedContext = context.RequestServices.GetRequiredService<IScopedContextProvider>();
    // Store the request in the scoped context with a unique key
    scopedContext.Set("GraphQL_QueryRequest", request);
    return Task.CompletedTask;
}

Step 2: Retrieve the Request in Your Service

Inject IScopedContextProvider directly into your ClientesQueries class to access the request:

public class ClientesQueries
{
    private readonly IReadOnlyQueryRequest? _queryRequest;

    public ClientesQueries(IScopedContextProvider scopedContextProvider)
    {
        // Safely retrieve the request from the scoped context
        if (scopedContextProvider.TryGet("GraphQL_QueryRequest", out IReadOnlyQueryRequest? request))
        {
            _queryRequest = request;
        }
    }

    // Use _queryRequest to build your optimized database queries...
}

Why This Is Better:

  • Decoupled from ASP.NET Core: No dependency on IHttpContextAccessor, so your logic isn't tied to web-specific infrastructure.
  • Easier Testing: You can mock IScopedContextProvider in unit tests without needing to spin up a full HttpContext.
  • HotChocolate-Native: Aligns with the framework's built-in patterns for request-scoped data sharing.

Option 2: Access the Request Directly in Resolvers (If Applicable)

If your ClientesQueries is directly used by GraphQL resolvers, you can skip the interceptor entirely and fetch the request from the resolver context:

public async Task<Cliente> GetCliente(int id, [Service] ClientesQueries clientesQueries, IResolverContext context)
{
    // Access the request directly from the resolver context
    var queryRequest = context.Request;
    return await clientesQueries.GetClienteById(id, queryRequest);
}

This is ideal if you only need the request within resolver workflows, as it eliminates the need for an interceptor altogether.

Option 3: Custom Query Execution Middleware

For more advanced scenarios, you can create a custom IQueryExecutionMiddleware to handle the request and pass it to downstream services. This gives you full control over the execution pipeline:

public class QueryRequestMiddleware : IQueryExecutionMiddleware
{
    private readonly QueryExecutionDelegate _next;

    public QueryRequestMiddleware(QueryExecutionDelegate next)
    {
        _next = next;
    }

    public async ValueTask<IQueryResult> InvokeAsync(IQueryContext context)
    {
        // Access the request from the query context
        var queryRequest = context.Request;
        
        // You can inject services here and pass the request to them,
        // or store it in scoped context for later access
        var scopedContext = context.Services.GetRequiredService<IScopedContextProvider>();
        scopedContext.Set("GraphQL_QueryRequest", queryRequest);

        return await _next(context);
    }
}

// Register the middleware in your startup
services.AddGraphQLServer()
    .AddQueryType<Queries>()
    .AddMiddleware<QueryRequestMiddleware>();

This approach is best if you need to modify or inspect the request at specific points in the execution pipeline.

Comparison to Your Original Approach

Your initial method works, but the IScopedContextProvider approach is more maintainable and testable. Avoiding IHttpContextAccessor reduces tight coupling to ASP.NET Core, making your code more portable if you ever need to run your GraphQL layer outside a web context.

内容的提问来源于stack exchange,提问作者Lucas Phillip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:38:12