Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In your ASP.NET MVC 3 applications that use a DataContext or DbContext, where do you instantiate your data access object?

Here is a non-exhaustive list of where I've seen it done:

  • Individually within each method of the controller
  • In the controller's constructor
  • As a property (lazy-initialized) of the controller
  • In an ActionFilter, shoved into ViewBag
  • In Global.asax Application_BeginRequest
  • In an HttpModule

I can't identify a clear front-runner amongst all of those. What's worse, whenever I start a brand-new project, I tend to change it up, just because.

Does anyone have any battle-tested advice?

share|improve this question
add comment

3 Answers

My dependency injection framework controls the creation and lifetime of the DbContext. The instantiation usually happens when the controller (or one of its dependencies) is instantiated.

share|improve this answer
2  
Sorry, but I don't find that particularly helpful. Ceding responsibility to a framework, and not knowing when the framework actually actually instantiates the object, doesn't seem like an answer (to me). –  Portman Mar 26 '11 at 2:24
1  
@Portman: Not sure what you mean. The DI container does exactly what I tell it to do through configuration rules. I said "usually" because the configuration and structure of my applications varies. In the simplest case of a controller directly dependent on the DbContext, it will be instantiated just before the controller. However, I often delegate data access to other services, and in that case the DbContext will be instantiated when these services need it. –  rmac Mar 26 '11 at 10:09
    
Do you have an example of your config? If you have other services dependent on DbContext, how do you ensure that the DbContext is destroyed at the end of the request? –  Portman Mar 26 '11 at 14:39
    
The MVC setup for Autofac is here: code.google.com/p/autofac/wiki/Mvc3Integration. Any dependencies registered to the HttpRequest Lifetime scope will be disposed when the request ends. –  rmac Mar 26 '11 at 19:55
add comment

Basically, I store it in HttpContext.Items, instantiating it the first time it is required, and re-using it if it is needed again. The lifespan of HttpContext.Items is the lifetime of the web request, so when all work for the request is complete, the data context is finished with.

I got the idea from story three in this blog post by Steven Sanderson, which also has some neat advice for extending that idea with inversion of control so there is no hard dependency between your data layer and HttpContext.

share|improve this answer
1  
That just sounds hacky and wrong. –  George Stocker Mar 25 '11 at 23:24
    
@George Stocker: Not that hacky or wrong if you aren't going the IoC route. Shouldn't access it directly all over the place from there, but it is the right backing store -- it is what most IoC containers use at the end of the day. –  Wyatt Barnett Mar 26 '11 at 2:17
    
@George: the implementation seems hacky and wrong? Or the outcome? The outcome to me seems optimal: one, and one only, data context per web request. And the implementation, while it's a little fiddly like IoC always is, effectively does the job of preventing the data layer from needing to know anything about web requests. Will you be providing the OP with an alternative approach? –  Carson63000 Mar 26 '11 at 4:10
    
Two words: Unit Testing. –  George Stocker Mar 26 '11 at 12:57
    
Two words, create your own HTTPRequest helper. This is very common approach when your unit testing sesssion base information. You obviously haven't been doinig too much unit testing. :) –  Nickz Apr 6 '11 at 3:20
show 2 more comments

For smaller projects I Basically, store it in HttpContext.Items. However, I love lazying loading, so I'm not a fan of spinning up a DBContext on literally every HttpApplication Request. So instead I wrote the following:

public static class ControllerExtensions
{
    public static MyDBContext MyDBContext(this Controller instance)
    {
        MyDBContext result = 
          instance.HttpContext.Items[typeof(MyDBContext).Name] as MyDBContext ;

        if (result == null)
        {
            result = new MyDBContext ();
            instance.HttpContext.Items[typeof(MyDBContext).Name] = result;
        }

        if (result == null)
        {
            throw new InvalidOperationException("No DBContext in HttpContext.");
        }

        return result;
    }

This means I have a Strongly-Typed, Lazy loaded, Single DBContext per Request, MyDBContext available for any controller to use.

public HomeController
{
  public ActionResult Index()
  {
    List<string> model = this.MyDBContext().Cars
                                           .Select(x => x.Name)
                                           .ToList();

    this.View(model);
  }
}
share|improve this answer
1  
how do you Dispose of the DbContext after the HttpContext has ended? –  freejelly Dec 29 '12 at 5:33
    
You can do it manually by implementing the global.asax Application_EndRequest, or don't dispose of it. –  Erik Philips Dec 29 '12 at 17:08
    
Wouldn't there be issues with thread affinity and the fact that DbContext isn't thread safe? –  Hexxagonal Jan 16 '13 at 16:11
    
It may be a static function, but the storage of the DBContext is in the (assumed) thread safe HttpContext.Items which is a HttpContext per calling thread. If one thread had access to another threads HttpContext, there would be bigger problems then thread problems (security). –  Erik Philips Mar 14 '13 at 22:03
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.