首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Asp.Net核心无法访问已处理的上下文实例

Asp.Net核心无法访问已处理的上下文实例
EN

Stack Overflow用户
提问于 2021-04-02 11:34:59
回答 1查看 1.5K关注 0票数 4

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

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

我得到的错误是:

无法访问已释放的上下文实例。造成此错误的一个常见原因是处理一个上下文实例,该实例是通过依赖项注入解析的,然后尝试在应用程序的其他位置使用相同的上下文实例。如果在上下文实例上调用“Dispose”,或者将其包装在using语句中,则可能会发生这种情况。如果您使用的是依赖注入,则应该让依赖注入容器负责处理上下文实例。对象名称:“AdminContext”

控制器

代码语言:javascript
复制
[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" });
    }
}

服务

代码语言:javascript
复制
public Task<List<LiveMonitoring>> GetAllAsync()
{
    return _repository.GetAll().Take(100).ToListAsync();
}

仓库

代码语言:javascript
复制
public IQueryable<TEntity> GetAll()
{
    try
    {
        return _adminContext.Set<TEntity>();
    }
    catch (Exception ex)
    {
        throw new Exception("Couldn't retrieve entities");
    }
}

有什么问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-02 18:18:12

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

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

代码语言:javascript
复制
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<IActionResult>,以支持async调用。

如果您实际上希望稍后(而不是在请求Get时)在回调中调用Get,则需要注入一个IServiceScopeFactory以在回调中为您的服务创建作用域,如下所示:

代码语言:javascript
复制
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注入控制器的构造函数(因为根本不使用它)。​

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66918696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档