我有一个使用EF Core进行数据库交互的ASP.Net Core Web API。DBContext生命周期在启动类中通过“依赖项注入”容器进行管理:
services.AddDbContext<MyDbContext>(opts =>
opts.UseSqlServer(Configuration.GetConnectionString("MyDbConnectionString")));
在Web GET方法中,我想使用一个后台任务来处理数据并将其保存到数据库中,但是在使用DBContext保存数据之前已将其释放。
public class MyController : Controller
{
private readonly MyDbContext _context;
public MyController(MyDbContext context)
{
_context = context;
}
[HttpGet("test")]
public async Task<IActionResult> Test(int id)
{
var item = _context.Items.SingleOrDefault(i => i.Id == id);
Task t = new Task(() => SaveAsync(_context));
t.Start();
return Ok(item);
}
private void SaveAsync(MyDbContext context)
{
//processing something for a while
context.SaveChanges();
}
}
问题是_context对象已被DI容器处理,并且出现以下错误:System.ObjectDisposedException:'无法访问已处置的对象。导致此错误的常见原因是,处理从依赖项注入中解决的上下文,然后稍后尝试在应用程序中的其他位置使用相同的上下文实例。如果在上下文上调用Dispose()或将上下文包装在using语句中,则可能会发生这种情况。如果您正在使用依赖项注入,则应让依赖项注入容器负责处理上下文实例。'
该错误对我来说很清楚,但是您知道在后台任务中保留_context的方法吗?
[如果您想做类似的事情,我建议您研究Background tasks with hosted services in ASP.NET Core。但是,要解决此错误,请尝试使用RegisterForDispose。还有一个异步版本。
HttpContext.Response.RegisterForDispose(_context);