c# - HotChocolate 解析和异步
问题描述
我正在使用带有实体框架的 HotChocolate。对于某些字段,我们希望过滤一对多集合。
例子 :
public class Many
{
public int Id { get; set; }
public string? Name {get; set; }
}
public class User
{
public int Id { get; set; }
public List<Many> Manies { get; set; }
}
public class UserType : ObjectType<User>
{
protected override void Configure(IObjectTypeDescriptor<User> descriptor)
{
descriptor.BindFieldsExplicitly();
descriptor.Field(u => u.Id);
descriptor.Field("manies").Resolve(c => c.Parent<User>().Manies.Where(m => m.Name.StartsWith("A")).ToList());
}
}
我的第一个问题是:解析器是否按照 v10 的HotChocolate 文档所述并行执行?
当我在解析器中使用 async/await 时,我也遇到了问题。似乎在这种情况下(并且仅在这种情况下)解析器是在另一个线程上启动的(并且我遇到了 DbContext 并行执行的问题)。
例子 :
descriptor.Field("manies").Resolve(async c => {
var parent = c.Parent<User>();
return await GetFilterManiesAsync(parent);
});
但是当我强制同步时,没有并行问题:
descriptor.Field("manies").Resolve(c => {
var parent = c.Parent<User>();
return GetFilterManiesAsync(parent).Result;
});
所以我想了解,这是 HotChocolate 中的错误吗?或者并行管道是否仅在 async/await 解析器上启动。
PS 使用 HotChocolate v11.0.9
谢谢,
解决方案
我建议您通过他们的官方graphql-workshop讨论这个和许多其他内容。其中的一堂课包含以下段落:
GraphQL 执行引擎将始终尝试并行执行字段,以优化数据获取并减少等待时间。实体框架会遇到问题,因为DBContext不是线程安全的。
解决这个问题的方法是使用DbContext
池化。使用DBContext
池允许您为每个需要的字段发出一个DBContext
实例。但是,不是DBContext
为每个字段创建一个实例并在使用后将其丢弃,而是租用字段和请求可以重用它。
要进行设置,您必须将您的注册DbContext
从更改services.AddDbContext<YourContext>(options => ...);
为services.AddPooledDbContextFactory<YourContext>(options => ...);
。然后,您需要注册YourContext
为一个作用域服务,每次从代码的某些部分访问它时,它都会从工厂本身解析。这样,您将允许库本身做它的事情并并行解析字段。
我不确定当您调用Result
并强制执行同步时会发生什么,但我猜您以某种方式设法阻止了整个并行字段解析。