2

If you create a WebAPI/MVC project in say Visual Studio 2013, add Model (and DbContext class), and a Controller for this model as outlined here-

http://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-2,

it creates a controller that declares the DbContext as a member variable, which is according to many stackoverflow answers/online arcticles, is a bad idea- like this one

https://stackoverflow.com/a/10588594

The controller methods generated by Visual Studio-

// GET: api/Authors
public IQueryable<Author> GetAuthors()
{
    return db.Authors;
}

Will not work if you use the recommended per request lifetime -

// GET: api/Authors
    public IQueryable<Author> GetAuthors()
    {
        DbSet<Author> authors = null;
        using(MyContext db = new MyContext) {
             authors = db.Authors;
        }
        return authors;
    }

Because the context is out of scope by the time the result is iterated over and you get an object disposed exception.

So, what's the correct way and if it is the "using" per request method, why does the VS template use the member variable method?

Community
  • 1
  • 1
user210757
  • 6,996
  • 17
  • 66
  • 115

1 Answers1

4

The reason is because it's a simple starting point.

It's easy to understand and easy to get started using ASP.NET MVC.

There's nothing really wrong with having a DbContext as a member variable that is created at a controller level, though it's probably not ideal. As an application becomes more complex, it just doesn't fit very well.

[ ... ] according to many stackoverflow answers/online arcticles, is a bad idea

I didn't get that from the answer that you linked at all.

Steven explains that a single DbContext (i.e. global) or a context per thread is bad.

Will not work if you use the recommended per request lifetime

That isn't a per-request lifetime. That's almost like a unit-of-work pattern, but you aren't doing anything with it.

The fix for what you're trying to do there would be

// GET: api/Authors
public IEnumerable<Author> GetAuthors()
{
    IEnumerable<Author> authors = null;

    using(MyContext db = new MyContext())
    {
         authors = db.Authors.ToList();
    }

    return authors;
}

In my opinion, the correct way of dealing with this is to use a per-web-request lifestyle for the DbContext with an IoC Container.

Showing a full example here is probably a bit lengthy and outside the scope of the question.

Rowan Freeman
  • 15,724
  • 11
  • 69
  • 100
  • great answer, accepted, thanks. what bothers me with the member variable in my ex, is it's like it's used after you leave the scope of the action method to actually get the results. also, a lot of the repository/uow examples just make the repository/uow class a member variable of the controller instead. I feel like that repository/uow class should also be rolled up in a using statement per action method... maybe it's the same difference. – user210757 Feb 20 '15 at 17:33
  • I think I agree with you. I just have created Web API service and tend to create DbContext instance per method... And let's monitoring tools show if there are any problems with such approach. – Alexander Jun 14 '17 at 07:00