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

如何在HotChocolate FieldResolver中获取当前实体ID关联错误数据?

问题描述

我编写了以下代码,想要从一个缓存错误以提升性能的服务中获取完整错误列表,为已解析的实体项附加错误列表:

public class MyEntityExtensions : ObjectType<MyEntity>
{
    protected override void Configure(IObjectTypeDescriptor<MyEntity> descriptor)
    {
        descriptor
            .Field("errors")
            .Type(typeof(List<Error>))
            .Resolve(async context =>
            {
                var errorCache = context.Service<ErrorCache>();

                var entityId = ???;

                var errors = await errorCache.Get(entityId);

                return errors ;
            });
    }
}

疑问点

  • 如何获取当前实体的Id属性,作为参数传入缓存服务?
  • 尝试过声明式方法,但无法强制执行解析器顺序或字段依赖;运行时方法里MiddlewareContext也没有持有同一对象其他字段的信息,唯一能引用已解析项的方式是.Parent<>(),但这不是层级结构。试过多种中间件设置和Use()调整执行顺序都没成功。
  • 当前方法是否可行?如果不可行,有没有不用把错误作为完全独立数据源拼接的替代方案?

解决方案

1. 获取当前实体的Id属性

在解析器中,你可以直接通过context.Parent<MyEntity>()获取当前正在处理的MyEntity实例,进而访问它的Id属性,这是最直接的方式:

.Resolve(async context =>
{
    var errorCache = context.Service<ErrorCache>();
    // 获取当前实体实例
    var currentEntity = context.Parent<MyEntity>();
    var entityId = currentEntity.Id;

    var errors = await errorCache.Get(entityId);
    return errors;
});

这里的context.Parent<T>()专门用于获取当前字段所属的父对象(也就是当前的MyEntity实例),它不需要依赖其他字段的解析顺序——因为这个字段的解析是基于已经加载完成的MyEntity实例本身,而非等待其他字段解析结果。

2. 当前方法的可行性及替代方案

你的当前方法是完全可行的,context.Parent<T>()就是正确获取当前实体实例的标准方式,如果之前用的时候没成功,大概率是配置问题,比如MyEntity的类型映射是否正确,或者解析上下文的父对象类型是否匹配。

如果需要更灵活的实现,还有两种替代方案:

  • 实体加载时预绑定错误:如果获取MyEntity的查询逻辑可以同时拉取错误数据,直接把错误作为MyEntity的一个属性,这样就不需要单独的字段解析器。但这种方式要注意性能,只有当错误数据和实体数据能批量加载时才推荐。
  • 批量加载错误提升性能:如果一次请求会处理多个MyEntity实例,可以通过全局中间件收集所有需要查询的entityId,批量从缓存获取错误后再分配给对应实体,避免多次缓存查询:
    // 批量加载错误的中间件示例
    public class BatchErrorLoadingMiddleware : IMiddleware
    {
        public async ValueTask InvokeAsync(IResolverContext context, MiddlewareDelegate next)
        {
            await next(context);
    
            // 标记需要批量查询错误的实体ID
            if (context.Field.DeclaringType.Name == nameof(MyEntity) && context.Field.Name == "errors")
            {
                var entityIds = context.BatchData.GetOrAdd("entityIds", () => new List<Guid>());
                var entity = context.Parent<MyEntity>();
                entityIds.Add(entity.Id);
            }
    
            // 在请求收尾阶段批量获取错误
            if (context.IsFinalResolver)
            {
                if (context.BatchData.TryGetValue("entityIds", out var idsObj) && idsObj is List<Guid> entityIds)
                {
                    var errorCache = context.Service<ErrorCache>();
                    var allErrors = await errorCache.GetBatch(entityIds);
                    context.BatchData["errorsMap"] = allErrors.ToDictionary(e => e.EntityId, e => e.Errors);
                }
            }
        }
    }
    
    之后在解析器中直接从批量数据中取对应实体的错误:
    .Resolve(async context =>
    {
        var currentEntity = context.Parent<MyEntity>();
        if (context.BatchData.TryGetValue("errorsMap", out var errorsObj) && errorsObj is Dictionary<Guid, List<Error>> errorsMap)
        {
            errorsMap.TryGetValue(currentEntity.Id, out var errors);
            return errors ?? new List<Error>();
        }
        return new List<Error>();
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:52:37