从“Scoped”切换到“Transient”并不能解决该问题,因为 Gql.Net 字段解析器是并行执行的。
根据你的例子,我希望你的DbContext
被构造函数注入到您的“数据库服务”类中(userQueryService
and groupQueryService
),并且这些被构造函数注入到您的示例 GraphType 类中。因此,您的每个数据库服务都具有完全相同的范围副本DbContext
.
解决方案是惰性解决你的DbContext
.
快速而肮脏的方法是使用“服务定位器”模式。
您将更改您的数据库服务以注入IServiceScopeFactory
。然后您可以在加载器方法中使用它(MyUserFunc
and MyGroupFunc
)创建一个范围,然后解决你的DbContext
。这种方法(“服务定位器”)的问题在于对您的依赖DbContext
隐藏在您的班级内。
更好的方法(类似,但不是“服务定位器”)...
在 Code Review.Stack Exchange 上使用这段相对简单的代码改为使用IServiceScopeFactory<T>
。您无需执行“服务定位器”即可获得延迟解析;您的强类型依赖项在构造函数中声明。
Example
所以假装你的userQueryService
变量的类是这样的:
MyDbContext _dbContext;
public UserQueryService(MyDbContext dbContext) => _dbContext = dbContext;
public async Task<IDictionary<Guid, IEnumerable<User>> MyUserFunc(IEnumerable<Guid> userIds)
{
// code that uses _dbContext and returns the data...
}
将其更改为此(再次使用IServiceScopeFactory<T>
):
IServiceScopeFactory<MyDbContext> _dbFactory;
public UserQueryService(IServiceScopeFactory<MyDbContext> dbFactory) => _dbFactory = dbFactory;
public async Task<IDictionary<Guid, IEnumerable<User>> MyUserFunc(IEnumerable<Guid> userIds)
{
using var scope = _dbFactory.CreateScope();
var dbContext = scope.GetRequiredService();
// code that uses dbContext and returns the data...
}
现在,当 Gql.Net 的解析器(在本例中是数据加载器)最终执行此方法时,每次使用您的DbContext
使用自己的作用域,因此他们不会像您现在那样遇到执行问题。