我正在尝试实现SignalR,以便使用来自角前端应用程序的数据。
我已经检查了谷歌上所有我能找到的结果,但我仍然无法解决我的问题。
我得到的错误是:
无法访问已释放的上下文实例。造成此错误的一个常见原因是处理一个上下文实例,该实例是通过依赖项注入解析的,然后尝试在应用程序的其他位置使用相同的上下文实例。如果在上下文实例上调用“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");
}
}有什么问题吗?
发布于 2021-04-02 18:18:12
我很确定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<IActionResult>,以支持async调用。
如果您实际上希望稍后(而不是在请求Get时)在回调中调用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注入控制器的构造函数(因为根本不使用它)。
https://stackoverflow.com/questions/66918696
复制相似问题