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

HotChocolate GraphQL子列表为Null时触发参数空引用错误求助

HotChocolate GraphQL 空列表字段引发的 Value cannot be null 异常解决

问题场景

执行以下GraphQL查询时:

{ name, userList { firstName, lastName } }

当返回的数百个对象中存在一个userList(列表类型)为Null的对象时,系统抛出异常:

Value cannot be null. (Parameter 'source')

即使已将userList属性标记为可空,问题依然存在。异常堆栈追踪如下:

at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
   at System.Linq.Enumerable.Select[TSource,TResult](IEnumerable`1 source, Func`2 selector)
   at lambda_method961(Closure, OrganizationResponse)
   at System.Linq.Enumerable.SelectIPartitionIterator`2.GetCount(Boolean onlyIfCheap)
   at System.Linq.EnumerableExecutor`1.Execute()
   at System.Linq.EnumerableQuery`1.System.Linq.IQueryProvider.Execute[TElement](Expression expression)
   at HotChocolate.Types.Pagination.QueryableOffsetPagingHandler`1.<>c__DisplayClass3_0.<ResolveAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
  at HotChocolate.Types.Pagination.QueryableOffsetPagingHandler`1.ResolveAsync(IResolverContext context, IQueryable`1 source, OffsetPagingArguments arguments, CancellationToken cancellationToken)
   at HotChocolate.Types.Pagination.OffsetPagingHandler.HotChocolate.Types.Pagination.IPagingHandler.SliceAsync(IResolverContext context, Object source)
   at HotChocolate.Types.Pagination.PagingMiddleware.InvokeAsync(IMiddlewareContext context)
   at HotChocolate.Utilities.MiddlewareCompiler`1.ExpressionHelper.AwaitTaskHelper(Task task)
   at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)
   at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)

问题原因

从堆栈信息可以看出,异常触发于QueryableOffsetPagingHandler的分页处理逻辑中。HotChocolate的自动分页中间件会尝试对列表字段执行Linq查询操作,当userList为Null时,Linq的Select方法接收到空的数据源,直接抛出参数空引用异常——即使字段标记为可空,分页逻辑仍会直接操作Null值而非跳过。

解决方案

1. 在Resolver中将Null转为空列表

在userList字段的Resolver方法里,显式将Null替换为空的Enumerable,避免分页逻辑处理空数据源:

public IEnumerable<User>? GetUserList(OrganizationResponse organization)
{
    // 若userList为Null,返回空列表而非Null
    return organization.UserList ?? Enumerable.Empty<User>();
}

2. 数据映射层提前处理Null

如果使用AutoMapper等工具做数据转换,在映射规则中配置将Null列表转为空列表:

public class OrganizationProfile : Profile
{
    public OrganizationProfile()
    {
        CreateMap<OrganizationDbModel, OrganizationResponse>()
            .ForMember(dest => dest.UserList, 
                opt => opt.MapFrom(src => src.UserList ?? new List<User>()));
    }
}

3. 禁用该字段的自动分页(可选)

如果该字段不需要分页功能,可以直接禁用HotChocolate的自动分页,避免分页逻辑介入:

[GraphQLIgnorePaging]
public IEnumerable<User>? UserList { get; set; }

4. 自定义分页Handler(复杂场景)

如果必须保留分页且需要处理Null场景,可以自定义分页Handler,在处理前检查数据源是否为Null:

public class NullSafeOffsetPagingHandler : OffsetPagingHandler
{
    protected override Task<IPage> SliceAsync(IResolverContext context, object source, CancellationToken cancellationToken)
    {
        // 若数据源为Null,返回空分页结果
        if (source == null)
        {
            return Task.FromResult<IPage>(new OffsetPage(Enumerable.Empty<object>(), 0, 0));
        }
        return base.SliceAsync(context, source, cancellationToken);
    }
}

然后在字段配置中指定使用该Handler:

descriptor.Field(t => t.UserList)
    .UsePaging<UserType>()
    .Handler<NullSafeOffsetPagingHandler>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 18:55:13