GraphQL Hot Chocolate Constructor DI 在第二次请求时失败
GraphQL Hot Chocolate Constructor DI failed on 2nd request
我正在构建一个带有用户身份验证服务的 GraphQL 端点。对于用户身份验证,我使用 Entity Framework Core.
在变异解析器中,当我使用构造函数 DI [Ref] 时,我在第二次访问解析器时出现以下错误。
“无法访问已释放的对象。\r\nObject 名称:'UserManager`1'。”
根据 Hot Chocolate 说明,构造函数 DI 是单例类型,不太确定为什么会出现此错误。
但是,如果我使用 [Service] 关键字注入解析器方法。我没有收到任何错误 [Ref].
public void ConfigureServices(IServiceCollection services)
{
services.AddGraphQLService();
services.AddDbContext<DataContext>(opt =>
{
opt.UseSqlite(_configuration.GetConnectionString("AuthenticationConnection"));
});
services.AddIdentityCore<User>(opt =>
{
opt.Password.RequireNonAlphanumeric = false;
})
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<DataContext>()
.AddSignInManager<SignInManager<User>>();
}
这是配置GrapghQL的扩展方法
public static IServiceCollection AddGraphQLService(this IServiceCollection services)
{
services.AddGraphQLServer()
.AddQueryType(q => q.Name("Query"))
.AddTypeExtension<AlbumQueryTypeExtension>()
.AddTypeExtension<ArtistQueryTypeExtension>()
.AddMutationType(m => m.Name("Mutation"))
.AddTypeExtension<ArtistMutationTypeExtension>()
.AddTypeExtension<AuthenticationMutationTypeExtension>()
.AddSubscriptionType<Subscription>()
.AddInMemorySubscriptions()
.AddAuthorization()
;
return services;
}
在我的解析器中,以下方法有效,
public async Task<User> LoginAsync(LoginDto loginDto, [Service] UserManager<User> userManager)
{
var user = await userManager.FindByEmailAsync(loginDto.Email);
return user ;
}
但是如果我做构造函数 DI,我会得到一个错误。
public class AuthenticationMutateResolvers
{
private readonly UserManager<User> _userManager;
public AuthenticationMutateResolvers(UserManager<User> userManager)
{
_userManager = userManager;
}
public async Task<User> LoginAsync(LoginDto loginDto)
{
var user = await _userManager.FindByEmailAsync(loginDto.Email);
return user;
}
}
知道为什么构造函数 DI 仅适用于第一个请求。
我做错了什么吗?
因此,如果您不声明任何内容,Hot Chocolate 会将解析器 class 添加为单例。在您使用 UserManager<User>
的情况下,我认为这是一项范围内的服务。因此,在您的案例中使用构造函数注入的每个解析器 class 都需要在 DI 中注册以及范围服务。
或者,您可以使用解析器级别的 DI。
public async Task<User> LoginAsync(LoginDto loginDto, [Service] UserManager<User> userManager)
{
var user = await userManager.FindByEmailAsync(loginDto.Email);
return user;
}
我个人倾向于使用解析器级别的 DI,因为它更清楚执行过程中需要什么。但这取决于你。
我正在构建一个带有用户身份验证服务的 GraphQL 端点。对于用户身份验证,我使用 Entity Framework Core.
在变异解析器中,当我使用构造函数 DI [Ref] 时,我在第二次访问解析器时出现以下错误。 “无法访问已释放的对象。\r\nObject 名称:'UserManager`1'。”
根据 Hot Chocolate 说明,构造函数 DI 是单例类型,不太确定为什么会出现此错误。
但是,如果我使用 [Service] 关键字注入解析器方法。我没有收到任何错误 [Ref].
public void ConfigureServices(IServiceCollection services)
{
services.AddGraphQLService();
services.AddDbContext<DataContext>(opt =>
{
opt.UseSqlite(_configuration.GetConnectionString("AuthenticationConnection"));
});
services.AddIdentityCore<User>(opt =>
{
opt.Password.RequireNonAlphanumeric = false;
})
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<DataContext>()
.AddSignInManager<SignInManager<User>>();
}
这是配置GrapghQL的扩展方法
public static IServiceCollection AddGraphQLService(this IServiceCollection services)
{
services.AddGraphQLServer()
.AddQueryType(q => q.Name("Query"))
.AddTypeExtension<AlbumQueryTypeExtension>()
.AddTypeExtension<ArtistQueryTypeExtension>()
.AddMutationType(m => m.Name("Mutation"))
.AddTypeExtension<ArtistMutationTypeExtension>()
.AddTypeExtension<AuthenticationMutationTypeExtension>()
.AddSubscriptionType<Subscription>()
.AddInMemorySubscriptions()
.AddAuthorization()
;
return services;
}
在我的解析器中,以下方法有效,
public async Task<User> LoginAsync(LoginDto loginDto, [Service] UserManager<User> userManager)
{
var user = await userManager.FindByEmailAsync(loginDto.Email);
return user ;
}
但是如果我做构造函数 DI,我会得到一个错误。
public class AuthenticationMutateResolvers
{
private readonly UserManager<User> _userManager;
public AuthenticationMutateResolvers(UserManager<User> userManager)
{
_userManager = userManager;
}
public async Task<User> LoginAsync(LoginDto loginDto)
{
var user = await _userManager.FindByEmailAsync(loginDto.Email);
return user;
}
}
知道为什么构造函数 DI 仅适用于第一个请求。
我做错了什么吗?
因此,如果您不声明任何内容,Hot Chocolate 会将解析器 class 添加为单例。在您使用 UserManager<User>
的情况下,我认为这是一项范围内的服务。因此,在您的案例中使用构造函数注入的每个解析器 class 都需要在 DI 中注册以及范围服务。
或者,您可以使用解析器级别的 DI。
public async Task<User> LoginAsync(LoginDto loginDto, [Service] UserManager<User> userManager)
{
var user = await userManager.FindByEmailAsync(loginDto.Email);
return user;
}
我个人倾向于使用解析器级别的 DI,因为它更清楚执行过程中需要什么。但这取决于你。