如何在基于HotChocolate的GraphQL中使用存储过程
在HotChocolate GraphQL中传递UserID/DB-Role到存储过程的实现方案
1. 注入用户身份信息到GraphQL请求上下文
先通过自定义请求拦截器,从HttpContext(比如JWT认证的Claims)中提取UserID和DB-Role,注入到GraphQL请求上下文:
public class CustomHttpRequestInterceptor : DefaultHttpRequestInterceptor { public override ValueTask OnCreateAsync(HttpContext context, IRequestExecutor requestExecutor, IQueryRequestBuilder requestBuilder, CancellationToken cancellationToken) { // 根据实际认证方式获取用户信息,这里以Claims为例 var userId = context.User.Claims.FirstOrDefault(c => c.Type == "userid")?.Value; var dbRole = context.User.Claims.FirstOrDefault(c => c.Type == "db-role")?.Value; // 将信息存入请求上下文 requestBuilder.SetProperty("UserId", userId); requestBuilder.SetProperty("DbRole", dbRole); return base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken); } }
然后在Program.cs中注册该拦截器:
builder.Services.AddGraphQLServer() .AddHttpRequestInterceptor<CustomHttpRequestInterceptor>() // 其他GraphQL配置(如添加查询类型、实体类型等)
2. 在解析器中获取上下文并调用存储过程
在GraphQL查询的解析器方法里,通过IResolverContext取出UserID和DB-Role,再结合Entity Framework执行存储过程:
方式一:使用EF Core的FromSqlRaw执行
public class Query { public async Task<List<YourEntity>> GetFilteredDataAsync( [Service] YourDbContext dbContext, IResolverContext context) { // 从上下文提取用户信息 var userId = context.GetProperty<string>("UserId"); var dbRole = context.GetProperty<string>("DbRole"); // 调用MySQL存储过程,参数化避免注入 var data = await dbContext.YourEntity .FromSqlRaw("CALL YourLegacyStoredProcedure({0}, {1})", userId, dbRole) .ToListAsync(); return data; } }
方式二:使用SqlCommand处理复杂存储过程(如带输出参数)
public async Task<List<YourEntity>> GetFilteredDataAsync( [Service] YourDbContext dbContext, IResolverContext context) { var userId = context.GetProperty<string>("UserId"); var dbRole = context.GetProperty<string>("DbRole"); using var command = dbContext.Database.GetDbConnection().CreateCommand(); command.CommandText = "YourLegacyStoredProcedure"; command.CommandType = CommandType.StoredProcedure; // 添加MySQL参数 command.Parameters.Add(new MySqlParameter("@UserId", userId)); command.Parameters.Add(new MySqlParameter("@DbRole", dbRole)); await dbContext.Database.OpenConnectionAsync(); using var reader = await command.ExecuteReaderAsync(); // 手动映射查询结果到实体类 var result = new List<YourEntity>(); while (await reader.ReadAsync()) { result.Add(new YourEntity { Id = reader.GetInt32(0), // 其他字段按存储过程返回结果映射 }); } return result; }
3. 补充配置与安全校验
- 注册查询类型和实体类型:
builder.Services.AddGraphQLServer() .AddHttpRequestInterceptor<CustomHttpRequestInterceptor>() .AddQueryType<Query>() .AddType<YourEntity>(); // 若需自定义字段映射,可创建YourEntityType类注册
- 添加授权校验,确保只有合法用户能访问查询:
[Authorize] public async Task<List<YourEntity>> GetFilteredDataAsync(...) { // 实现逻辑 }
内容的提问来源于stack exchange,提问作者puneeth.c.s
相关产品推荐
相关产品推荐

