GraphQL Hot Chocolate构造函数DI在第二次请求时失败问题咨询
核心原因
你遇到的是典型的服务生命周期不匹配问题:
- Hot Chocolate默认将所有解析器类(包括你注册的TypeExtension)注册为单例,解析器构造函数注入的服务会和解析器本身生命周期绑定,会一直存在于解析器的整个生命周期里。
- 你用
AddIdentityCore注册的UserManager<User>,以及依赖的DataContext,默认都是Scoped生命周期,只会在单次请求的范围内存活,请求结束就会被DI容器释放。
第一次请求触发解析器初始化,构造函数拿到的是当前请求Scope里的UserManager,所以第一次调用正常;第一次请求结束后Scope销毁,UserManager被释放,单例解析器里保存的UserManager引用就变成了已释放的对象,第二次请求再调用就会抛出对象已释放的错误。
而你在解析器方法参数上加[Service]注入服务时,Hot Chocolate每次调用方法都会从当前请求的Scope中获取对应服务,每次拿到的都是当前请求存活的可用实例,所以不会出现释放问题,这也是Hot Chocolate官方推荐的Scoped/Transient服务注入方式。
正确的配置方案
有两种可行方案,根据你的使用习惯选择即可:
方案1(官方推荐):保持方法级[Service]注入
不用调整现有解析器注册逻辑,所有Scoped/Transient服务都通过方法参数的[Service]标记注入,避免生命周期不匹配问题,代码和你现在正常运行的写法一致。
方案2:修改解析器类的生命周期为Scoped
如果你坚持要用构造函数注入Scoped服务,只需要在注册TypeExtension时指定Scoped生命周期即可,修改你的AddGraphQLService方法里的对应代码:
// 原来的写法 // .AddTypeExtension<AuthenticationMutationTypeExtension>() // 修改为指定Scoped生命周期 .AddTypeExtension<AuthenticationMutationTypeExtension>(ServiceLifetime.Scoped)
注意所有依赖Scoped服务的TypeExtension都需要修改生命周期,否则还是会出现同样的问题。
内容的提问来源于stack exchange,提问作者Ash
相关产品推荐
相关产品推荐

