Asp.Net Core 无法访问已释放的上下文实例
Posted
技术标签:
【中文标题】Asp.Net Core 无法访问已释放的上下文实例【英文标题】:Asp.Net Core Cannot access a disposed context instance 【发布时间】: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文件 【参考方案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<IActionResult>
以支持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
注入控制器的构造函数(因为它根本没有被使用)。
【讨论】:
以上是关于Asp.Net Core 无法访问已释放的上下文实例的主要内容,如果未能解决你的问题,请参考以下文章
注入 DbContext 时无法访问 ASP.NET Core 中已释放的对象
在 Asp.NET core 中触发 Quartz 作业时释放上下文
C#:使用 IQueryable 注入 DbContext 时,无法访问 ASP.NET Core 中的已处置对象
在 ASP.NET Core Authorize-Attribute 中使用带有 DbContext 的存储库:“无法访问已处置的对象”