我使用版本 11.0.9 的 GraphQL HotChocolate nuget(HotChocolate.AspNetCore 和 HotChocolate.Types.Filters)(需要使用相当旧的版本,但甚至在 13.9.14 中也已重现),并启用了集合过滤功能。 一般来说,过滤效果很好,但对于某些查询,它会在过滤期间(中间件阶段)导致 NullReferenceException。
位详细信息(我创建了一个小项目来重现此问题):
public class Item
{
public int Id { get; set; }
public ItemSetting ItemSetting { get; set; }
public IEnumerable<Category> Categories { get; set; }
}
public class ItemSetting
{
public int Data { get; set; }
}
public class Category
{
public string Name { get; set; }
}
[UseFiltering]
public IEnumerable<Item> GetItems()
{
return [
new Item
{
Id = 1,
ItemSetting = new ItemSetting
{
Data = 123
},
Categories = [ new Category
{
Name = "Cat1"
}]
},
new Item
{
Id = 2,
ItemSetting = null,
Categories = [ new Category
{
Name = "Cat2"
}]
}
];
}
并查询,导致错误:
查询 { items(where: {categories_some: {name: "Cat1"}, itemSetting: {data: 123}}) { id itemSetting { data }categories { name } } }
错误本身:
{ "errors": [ { "message": "意外的执行错误", "locations": [ { "line": 2, "column": 3 } ], "path": [ "items" ], "extensions ": { "message": "对象引用未设置到对象的实例。", "stackTrace": " at lambda_method83(Closure, Item) 在 System.Linq.Enumerable.WhereEnumerableIterator 1.MoveNext() 在 HotChocolate.Execution.Processing.ResolverTask.<>c__DisplayClass13_0.b__0() 在 System.Threading.Tasks.Task 1.InnerInvoke() 在System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(线程threadPoolThread,ExecutionContextexecutionContext,ContextCallback回调,对象状态) --- 先前位置的堆栈跟踪结束 --- 在System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(线程threadPoolThread,ExecutionContextexecutionContext,ContextCallback回调,对象状态) 在 System.Threading.Tasks.Task.ExecuteWithThreadLocal(任务& currentTaskSlot,线程 threadPoolThread) --- 先前位置的堆栈跟踪结束 --- 在HotChocolate.Execution.Processing.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken取消令牌) 在 HotChocolate.Execution.Processing.ResolverTask.TryExecuteAsync(CancellationToken CancellationToken)" } } ], "data": { "items": null } }
奇怪的是,如果我改变过滤条件的顺序,没有问题:
items(其中:{ itemSetting:{data:123},categories_some:{name:“Cat1”}})
我进行了一些调查,看起来 QueryableFilterVisitor (来自 nuget)以错误的顺序为 IQueriable 创建了表达式(首先检查 downData 的值,然后检查 downItemSetting 对象不为空)。
我有一个小项目可以在需要时重现此问题(https://github.com/olu-lebara/FilterIssueTest)。 请帮助找出任何解决办法。因为更改订单的解决方法不适用于我的情况(客户不知道这个问题)。
您可以更改 data 属性的可空性,而不是 itemSetting 属性(我的意思是:https://github.com/RenatV/FilterIssueTest)或使用新的额外字段,因为 itemSetting 为空标记并检查它们(itemSetting 属性也必须不可为空
public ItemSetting ItemSetting { get; set; } = new();
)。