Programming

Entity Framework Core: DbContext disposed in async method

Last night I stumbled on an interesting piece of behaviour regarding Entity Framework Core and a method that executed a task.

I tried to execute following code:

[HttpGet()]
public async void LoadLists()
{
var task = new GetListTask();
var result = await task.GetListsAsync();

foreach (var list in result.Lists)
{
_dbContext.Lists.Add(list);
}
_dbContext.SaveChanges();
}

However I would always get an Exception thrown that  the _context object was disposed already. After trying different things and googling I found following post on Stackoverflow: https://stackoverflow.com/a/35988460

Basically the async void signature in the method is the culprit of this thrown exception. This will result in a disposal of the _context object when await is called for the first time. This is happening because the method cannot be awaited when the return type is void.

So basically changing the return type into Task will make the method awaitable and the _context variable will not be thrown away.

Thus, although WebAPI does support asynchronous methods, when invoking your action it seems as if it was a synchronous void returning method, and then the ASP.NET runtime goes on to dispose your controller, because it assumes that you’re done with the action.

When exposing a Task or Task, you’re explicitly telling the caller “Listen, this method is asynchronous an will eventually return a value in the future”. The ASP.NET runtime knows your controller hasn’t finished invoking his action, and awaits upon the actual completion of the action.

So eventualy this should work:

[HttpGet()]
public async Task LoadLists()
{
var task = new GetListTask();
var result = await task.GetListsAsync();

foreach (var list in result.Lists)
{
_dbContext.Lists.Add(list);
}
_dbContext.SaveChanges();
}