But if async is used, this Dispose method is called upon the first appearance.
@ The answer to Konstantins is correct, but let me elaborate on why this is happening. When you use the async void method, you basically create the fire and forget semantics to call the method, because any caller of this method cannot asynchronously wait on it with await , since it returns void and not the expected form (for example, Task ).
Thus, although the WebAPI supports asynchronous methods, when you call your action, it seems like it was a synchronous void return method, and then the ASP.NET runtime continues to control your controller, as it assumes, done with the action.
When exposing a Task or Task<T> you explicitly tell the caller, "Listen, this method is asynchronous and will eventually return a value in the future." ASP.NET runtime knows that your controller has not yet completed a call to its action and expects the action to actually complete.
This is why the challenge is this:
[HttpPost] public async Task DoStuffAsync(string id) { var entity = await _db.Estates.FindAsync(id); _db.SaveChanges(); }
Works.
As a side note - EF DbContext should be used and removed as soon as possible. Using them as a global variable for several actions is a bad idea, since they are not thread safe . I would suggest another template in which each action is initialized and places a DbContext :
[HttpPost] public async Task DoStuffAsync(string id) { using (var db = new EstateContext()) { var entity = await db.Estates.FindAsync(id); db.SaveChanges(); } }
As @Wachburn noted in the comments, this approach is really less tested. If you guarantee that your controller and action will be deleted after completing each action and reusing the context, you can enter DbContext through the DI container.
Yuval Itzchakov
source share