我在实体框架中使用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());
}
}我的第一个问题是:解析器是否按照HotChocolate文档 for v10的规定并行执行?
此外,当我在Resolver中使用异步/等待时,我也遇到了问题。在这种情况下(只有在这种情况下),解析器似乎是在另一个线程上启动的(我对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中的一个bug吗?或者是仅在异步/等待解析器上启动并行管道。
P.S.使用HotChocolate v11.0.9
谢谢,
发布于 2021-04-01 00:45:11
我建议你通过他们的官方石墨车间来讨论这件事和其他很多事情。其中一次讲座包括以下段落:
GraphQL执行引擎将始终尝试并行执行字段,以优化数据获取和减少等待时间。实体框架会出现问题,因为DBContext并不是线程安全的。
解决这个问题的方法是使用DbContext池。使用DBContext池可以为需要的每个字段发出一个DBContext实例。但是,您不是为每个字段创建一个DBContext实例并在使用它之后将其丢弃,而是租用字段和请求来重用它。
为此,您必须将DbContext的注册从services.AddDbContext<YourContext>(options => ...);更改为services.AddPooledDbContextFactory<YourContext>(options => ...);。然后,您需要将YourContext注册为一个作用域服务,每当从代码的某个部分访问它时,该服务就会从工厂本身解析。这样,您将允许库本身执行它的任务,并并行地解析字段。
我不太清楚当您调用Result并强制执行同步时会发生什么,但我想您通过这样做成功地阻止了整个并行字段解析。
发布于 2022-07-25 11:10:24
也许您希望在注册服务上使用ServiceKind.Synchronized,以便始终执行DbContext同步。
https://stackoverflow.com/questions/66875998
复制相似问题