Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does no one disposes DbContext after WebApi controller operation?

I am aware of various tutorials as well as complete examples targeting WebApi & Entity Framework (even from Microsoft) that have WebApi controller like this:

public HttpResponseMessage GetInternet(int id) {
    var context = new InternetDbContext();
    var result =
       (from internet in context.Internets
        where internet.Id.Equals(id)
        select internet).FirstOrDefault();
    if(result != null)
       Request.CreateResponse(HttpStatusCode.OK, result);
}

But when I learnt about Entity Framework like 2 years ago, every resource I found about the framework pointed out how extremely important it is to DISPOSE the DbContex in the SHORTEST possible lifespan, e.g. with 'using'. And nowadays, people seem to don't give a shit about disposing anything (their managers, repositories, DI containers...).

Am I missing something here? Does the end of the API call automatically disposes the context? Or do I have to use something like HttpRequestMessageExtensions.RegisterForDispose() from http://msdn.microsoft.com/en-us/library/dn153859(v=vs.118).aspx?

like image 220
Acrotygma Avatar asked Dec 30 '13 09:12

Acrotygma


People also ask

Does DbContext need to be disposed?

Don't dispose DbContext objects. Although the DbContext implements IDisposable , you shouldn't manually dispose it, nor should you wrap it in a using statement. DbContext manages its own lifetime; when your data access request is completed, DbContext will automatically close the database connection for you.

How do you know if DbContext is disposed?

You don't need to check if it's disposed or not because if your DbContext is injected by the DI system then you'll never need to dispose it yourself because it will only be disposed at the end of the controller's lifespan (i.e. after the Action completes but before the View renders.

How do I dispose of DbContext in EF core?

When the controller is being disposed, call dispose on your repository and that should dispose the context. If you are using a service layer and not talking to the repository directly from the controller, then call dispose on the service which will call dispose on repo which will dispose the context.

Does DbContext implement IDisposable?

Second, the DbContext class does indeed implement IDisposable out of the box.


2 Answers

Personally, whenever I see the type implements IDisposable, I'm almost certain that I'm going to use a using statement when working with new instances of this type.

When the variable goes out of scope (like in your case with the context variable going out of scope when the execution returns from GetInternet method), its memory is eventually going to be reclaimed by garbage collector but this doesn't mean that any native handlers (e.g. file handlers or database connections) are going to be closed which can have a very serious negative impact on your application.

So, consider always wrapping an IDisposable into the using construct:

using (var context = new InternetDbContext())
{
  // Your code goes here
}

Hope this helps.

like image 168
volpav Avatar answered Oct 28 '22 17:10

volpav


Sometimes it is a bad idea to dispose the context. For example, I have a WebAPI2 controller method like this,

    [Route("Questionnaires")]
    public IEnumerable<Questionnaire> GetAllQuestionnaires()
    {
        NMQContext context = new NMQContext();
        return context.Questionnaires.AsEnumerable();
    }

The result data is a JSON list, and the Questionnaire is a compound object -- it contains entities from multiple database tables. If I wrap this with "using" I get an error, such as

   "Message": "An error has occurred.",
   "ExceptionMessage": "The operation cannot be completed because the DbContext has been disposed.",

If you are trying to serialize compound objects, then it is better NOT to dispose the connection. It is better to let the EF handle it for you. You could probably fix it by explicit eager loading, but that is painful. Don't do it.

like image 33
John Henckel Avatar answered Oct 28 '22 16:10

John Henckel