首页 > 解决方案 > 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

谢谢,

标签: c#entity-framework-corehotchocolate

解决方案


我建议您通过他们的官方graphql-workshop讨论这个和许多其他内容。其中的一堂课包含以下段落:

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

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

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

我不确定当您调用Result并强制执行同步时会发生什么,但我猜您以某种方式设法阻止了整个并行字段解析。


推荐阅读