You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET项目GraphQL中MyDataContext已释放报错,如何调整服务注册?

问题描述

在GraphQL Playground测试时出现以下错误:

Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'MyDataContext'.

项目相关代码如下:

Program.cs 注册代码

builder.Services.AddAdvancedDependencyInjection();
builder.Services.Scan(p => p.FromAssemblies(assemblies)
    .AddClasses()
    .AsMatchingInterface());

builder.Services.AddDbContext<MyDataContext>();

builder.Services.AddGraphQLServer()
    .AddQueryType<MyDataQuery>()
    .AddFiltering()
    .AddSorting()
    .ModifyRequestOptions(opt => opt.IncludeExceptionDetails = true);

MyDataQuery.cs 查询代码

class MyDataQuery 
{
    private readonly IDataService _dataService;

    public MyDataQuery(IDataService dataService) 
    {
         _dataService = dataService;
    }

    [UsePaging]
    [HotChocolate.Types.UseFiltering]
    [HotChocolate.Types.UseSorting]
    public async Task<IQueryable<Data>> Data() 
    {
        var data = _dataService.GetData();
        data.ToList(); // 此处报错,因为dataContext已被释放

        // 一些异步操作
    }
}

DataService 服务实现

public class DataService : IDataService
{
    public readonly MyDataContext _context;

    public DataService (MyDataContext context)
    {
        _context = context;
    }

    public IEnumerable<Data> GetData()
    {
        return _context.Data;
    }
}

通过控制器调用IDataService一切正常,但GraphQL调用时触发上述错误,请问如何调整服务/DataContext的注册方式让GraphQL正常工作?


解决方案

问题根源

默认AddDbContext注册的DbContext是Scoped(请求作用域)生命周期,但HotChocolate的查询类型(如MyDataQuery)默认是Singleton(单例)。单例服务会在应用启动时创建,若它依赖的IDataService也被注册为单例,就会导致MyDataContext在请求结束后被释放,但单例的DataService仍持有其引用,后续GraphQL请求调用时就会触发已释放错误。

具体修复步骤

  1. 将IDataService注册为Scoped生命周期
    由于DataService依赖Scoped的DbContext,它本身必须使用Scoped生命周期,避免生命周期不匹配。修改Scan注册代码:

    builder.Services.Scan(p => p.FromAssemblies(assemblies)
        .AddClasses()
        .AsMatchingInterface()
        .WithScopedLifetime()); // 新增该行指定Scoped生命周期
    
  2. 让GraphQL查询类型使用Scoped生命周期
    HotChocolate默认将查询类型注册为Singleton,需显式指定为Scoped,确保每个GraphQL请求都获取新的实例,使用当前请求的DbContext:

    builder.Services.AddGraphQLServer()
        .AddQueryType<MyDataQuery>()
        .AddFiltering()
        .AddSorting()
        .ModifyRequestOptions(opt => opt.IncludeExceptionDetails = true)
        .AddScopedQueryType<MyDataQuery>(); // 显式注册为Scoped
    

    也可全局设置所有GraphQL类型的默认生命周期为Scoped:

    builder.Services.AddGraphQLServer()
        .SetDefaultServiceLifetime(ServiceLifetime.Scoped) // 全局默认Scoped
        .AddQueryType<MyDataQuery>()
        .AddFiltering()
        .AddSorting()
        .ModifyRequestOptions(opt => opt.IncludeExceptionDetails = true);
    
  3. 优化数据查询逻辑(可选但推荐)
    _context.Data本质是IQueryable,直接返回它可让HotChocolate的过滤、排序、分页在数据库层面执行,提升性能,同时避免提前调用ToList()导致的上下文释放问题:

    // 修改DataService的GetData方法
    public IQueryable<Data> GetData()
    {
        return _context.Data;
    }
    
    // 修改MyDataQuery的Data方法
    public IQueryable<Data> Data() 
    {
        return _dataService.GetData();
        // 移除不必要的ToList(),由HotChocolate处理后续查询操作
    }
    

内容的提问来源于stack exchange,提问作者Febertson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:13:22