我正在构建一个带有用户身份验证服务的GraphQL端点。对于用户身份验证,我使用实体框架核心。
在突变解析器中,当我使用构造函数DI [Ref]时,我在第二次访问解析器时得到以下错误。无法访问已处置的对象。rnObject name: 'UserManager ' 1'.">
根据Hot Chocolate指令,构造函数DIs是单例类型,我不太确定为什么会得到这个错误。
然而,如果我在解析器方法中使用[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>>();
}
这是配置graphql
的扩展方法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将把解析器类添加为单例。就你的UserManager<User>
而言,我认为这是一项有范围的服务。因此,在这种情况下,每个使用构造函数注入的解析器类都需要在DI中注册,同时也需要注册一个有作用域的服务。
或者你可以使用解析器级别的DI。
public async Task<User> LoginAsync(LoginDto loginDto, [Service] UserManager<User> userManager)
{
var user = await userManager.FindByEmailAsync(loginDto.Email);
return user;
}
我个人倾向于使用解析器级别的DI,因为它更清楚在执行过程中需要什么。但这取决于你。