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());
  }
}

我的第一个问题是:解析器是否按照 Concat for v10 所述并行执行?

我在解析器中使用 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 解析器上启动。

附言使用 HotChocolate v11.0.9

谢谢,

解决方法

我建议您阅读他们的官方graphql-workshop,其中讨论了这个问题以及其他很多内容。其中的一个讲座包含以下段落:

GraphQL 执行引擎将始终尝试执行 并行以优化数据获取并减少等待时间。 实体框架将有一个问题,因为 DBContext 是 不是线程安全的。

解决这个问题的方法是使用 lexer.mll 池化。使用 DbContext 池化允许您为每个需要一个的字段发出一个 DBContext 实例。但不是为每个字段创建一个 DBContext 实例并在使用后将其丢弃,而是租用以便字段和请求可以重用它。

要进行设置,您必须将 DBContext 的注册从 DbContext 更改为 services.AddDbContext<YourContext>(options => ...);。然后,您需要将 services.AddPooledDbContextFactory<YourContext>(options => ...); 注册为范围服务,每次从代码的某些部分访问时,该服务都会从工厂本身解析。这样您就可以让库本身做它的事情并并行解析字段。

我不确定当您调用 YourContext 并强制执行同步时会发生什么,但我猜您通过这样做以某种方式设法阻止了整个并行场解析。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...