【问题标题】:Asp.Net Core Cannot access a disposed context instanceAsp.Net Core 无法访问已释放的上下文实例
【发布时间】:2021-06-29 06:55:57
【问题描述】:

我正在尝试实现 SignalR,以便使用来自 Angular 前端应用程序的数据。

我已经在谷歌上检查了所有我能找到的结果,但我仍然无法解决我的问题。

我得到的错误是:

无法访问已释放的上下文实例。造成这种情况的一个常见原因 错误正在处理已解决的上下文实例 依赖注入,然后尝试使用相同的上下文 在您的应用程序的其他地方实例。如果您是 在上下文实例上调用“Dispose”,或将其包装在 using 陈述。如果你使用依赖注入,你应该让 依赖注入容器负责处理上下文 实例。对象名称:'AdminContext'

控制器

[Route("api/[controller]")]
[ApiController]
public class ChartController : ControllerBase
{
    private IHubContext<ChartHub> _hub;
    private readonly ILiveMonitoringService _service;

    public ChartController(IHubContext<ChartHub> hub, ILiveMonitoringService service)
    {
        _hub = hub;
        _service = service;

    }
    public IActionResult Get()
    {
        var timerManager = new TimerManager(async () => await _hub.Clients.All.SendAsync("transferchartdata", await _service.GetAllAsync()));
        return Ok(new { Message = "Request Completed" });
    }
}

服务

public Task<List<LiveMonitoring>> GetAllAsync()
{
    return _repository.GetAll().Take(100).ToListAsync();
}

存储库

public IQueryable<TEntity> GetAll()
{
    try
    {
        return _adminContext.Set<TEntity>();
    }
    catch (Exception ex)
    {
        throw new Exception("Couldn't retrieve entities");
    }
}

可能是什么问题?

【问题讨论】:

  • 能否分享一下starup.cs文件

标签: asp.net-core entity-framework-core signalr asp.net-core-signalr


【解决方案1】:

我很确定 TimerManager 是您的问题。您没有显示它的声明,但看起来它的构造函数接受了一个回调,稍后会调用。这就是问题所在。您的作用域服务_service 将在回调中捕获并在稍后的某个时间点使用当请求已经结束时。所以在请求结束后,DbContext 被释放,你的 _service 将消耗一个释放的上下文。

解决方法是在将数据传递到回调之前先简单地获取数据,这样_service 就不会被捕获到回调中,如下所示:

public async Task<IActionResult> Get()
{
    var liveMonitorings = await _service.GetAllAsync();
    var timerManager = new TimerManager(async () => await _hub.Clients.All.SendAsync("transferchartdata", liveMonitorings));
    return Ok(new { Message = "Request Completed" });
}

我们需要将Get的返回类型改为Task&lt;IActionResult&gt;以支持async调用。

如果您确实想稍后在回调中调用_service.GetAllAsync()(而不是在请求Get 时),则需要注入IServiceScopeFactory 以在该回调中为您的服务创建范围,像这样:

public IActionResult Get([FromServices] IServiceScopeFactory serviceScopeFactory)
{
    var timerManager = new TimerManager(async () => 
                           {
                             using(var scope = serviceScopeFactory.CreateScope()){
                               var service = scope.ServiceProvider.GetRequiredService<ILiveMonitoringService>();                                   ​
                               ​var liveMonitorings = await service.GetAllAsync();
                               ​return await _hub.Clients.All.SendAsync("transferchartdata", liveMonitorings);
                            ​ }
                           ​});
   ​return Ok(new { Message = "Request Completed" });
}

这样您就不需要将_service 注入控制器的构造函数(因为它根本没有被使用)。 ​

【讨论】:

    猜你喜欢
    • 2021-03-29
    • 2022-10-13
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    • 2016-12-06
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多