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

如何解决ASP.NET Core 5 SignalR操作报Cannot access a disposed context instance错误

问题根因

你报错的核心原因是 Destroy 方法使用了 async void 签名。
SignalR 运行时无法跟踪 async void 方法的执行状态,会认为方法执行完成后直接释放依赖注入的 HaglandContext 实例,而此时你的删除逻辑还在异步执行,就会触发「无法访问已释放的上下文实例」错误。

修复步骤

1. 调整Hub方法签名

将 Destroy 方法的返回值从 void 改为 Task,让SignalR可以等待方法完全执行完成后再释放资源:

// 修改前
public async void Destroy(ViewNewswires model)

// 修改后
public async Task Destroy(ViewNewswires model)

仅这一步修改就可以解决90%的上下文释放报错。

2. 优化查询逻辑避免数据读取器冲突

你之前去掉ToList()触发的「未释放的打开数据读取器」错误,是因为IQueryable的延迟执行特性,循环遍历关联数据时还保持着数据库连接,同时执行删除操作就会出现并发读取冲突。
建议在仓储层补充异步查询方法,避免同步查询阻塞和延迟执行的问题:

补充仓储接口定义

// IRepository.cs 新增方法
using System.Linq.Expressions;

public interface IRepository<TEntity> where TEntity : class
{
    // 原有方法保留
    Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate);
    Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
}

补充仓储实现

// Repository.cs 新增实现
public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate)
{
    return await _context.Set<TEntity>().Where(predicate).ToListAsync();
}

public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
{
    return await _context.Set<TEntity>().FirstOrDefaultAsync(predicate);
}

调整Destroy方法的查询逻辑

public async Task Destroy(ViewNewswires model)
{
    // 全部改为异步查询,提前把数据加载到内存
    var nwc = await _newswireCharterer.GetListAsync(x => x.Newswire_Id == model.Id);
    var nwo = await _newswireOwner.GetListAsync(x => x.Newswire_Id == model.Id);
    var nwp = await _newswireProject.GetListAsync(x => x.Newswire_Id == model.Id);
    var nwr = await _newswireRegion.GetListAsync(x => x.Newswire_Id == model.Id);
    var nws = await _newswireScope.GetListAsync(x => x.Newswire_Id == model.Id);
    var nwv = await _newswireVessel.GetListAsync(x => x.Newswire_Id == model.Id);

    foreach (var charterer in nwc) await _newswireCharterer.DeleteAsync(charterer);
    foreach (var owner in nwo) await _newswireOwner.DeleteAsync(owner);
    foreach (var project in nwp) await _newswireProject.DeleteAsync(project);
    foreach (var region in nwr) await _newswireRegion.DeleteAsync(region);
    foreach (var scope in nws) await _newswireScope.DeleteAsync(scope);
    foreach (var vessel in nwv) await _newswireVessel.DeleteAsync(vessel);

    var nw = await _newswires.FirstOrDefaultAsync(x => x.Id == model.Id);
    await _newswires.DeleteAsync(nw);

    await Clients.OthersInGroup(GetGroupName()).SendAsync("destroy", model);
}

可选方案:使用DbContext工厂控制生命周期

如果你的删除逻辑执行时间较长,或者频繁出现上下文生命周期冲突,可以改用IDbContextFactory自己控制上下文的创建和释放,完全避开DI容器的生命周期限制:

  1. 注册上下文工厂
// Program.cs
builder.Services.AddDbContextFactory<HaglandContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("你的连接字符串名")));
  1. Hub中注入工厂,在方法内创建上下文操作即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 00:54:04