What is the best way to instantiate and dispose DbContext in MVC?
Solution 1
I would suggest you use a Dependency Injection framework. You can register your DbContext
as per request
container.RegisterType<MyDbContext>().InstancePerHttpRequest();
And inject it as a constructor parameter to the controller.
public class MyController : Controller
{
public MyController(MyDbContext myDbContext)
{
_myDbContext = myDbContext;
}
}
If the registered type implements IDisposable
then the DI framework will dispose it when the request ends.
1st approach: It is much more cleaner to use ID framework than manually implementing it. Further all your requests may not need your UoW.
2nd approach: The controller should not know how to construct your UoW(DbContext). Purpose is not reduce the coupling between components.
Solution 2
We currently use repositories injected with UoW (unit of work) instantiated via service locator from an repository factory. Unity controls the lifetime this way taking the work away from you.
Your particular implementation will vary depending if your using POCO's, Entity Objects, etc..
Ultimately you want UoW if your going to be working with more than one objectset in your controller to ensure your just using one context. This will keep your transactions in check etc.
If your going to use multiple objectcontexts (ie. multiple EDMX's), you'll want to look at using UoW with MSDTC...but thats probably more than you wanted to know. In the end, the important thing is to ensure you just instantiate what you need for the controller action (i.e. one instance of the context.). I don't think I'd go with Begin_Request, you may not even need the context for every request.
YMC
Updated on June 03, 2022Comments
-
YMC almost 2 years
MVC 3 + EF 4.1
I'm choosing between two approaches to deal with DbContext:
- Instantiate in
Application_BeginRequest
, put it intoHttpContext.Current.Items
and dispose inApplication_EndRequest
. - Create disposable UnitOfWork (kindof wrapper for
DbContext
) and start each controller action withusing(var unitOfWork = new UnitOfWork()) { ... }
Share your experience please: Which one would you prefer? what are pros and cons for each approach?
- Instantiate in
-
Thomas Levesque over 12 yearsThe OP said nothing about putting the DbContext in a static field... he wants to put it in HttpContext.Current.Items, which is perfectly safe as far as I can see
-
YMC over 12 yearsI did not say I put DbContext into global.asax. I said I put code that instantiates and disposes DbContext. DbContext is in HttpContext.Current.Items. It's thread-safe.
-
YMC over 12 yearsRight, it's better to use IoC container than handling BeginRequset and EndRequest, but it still seems to me pretty close to number 1, that's why I've not even extracted it as separate approach. What is more important for me is to compare 2 ways to access and control life cycle of DbContext (=Unit Of work): first way implies ASP.NET/IoC infrastructure is responsible for it, second one is about every controller action to be in charge.
-
Eranga over 12 years@YMC Edited answer. Your 2nd approach will introduce coupling between your controller and UoW implementation. I suggest you avoid it.
-
marvelTracker over 12 yearsIntroduce Service Layer and inject services to Controller. Service can have many repositories and repositories depend on UnitOfWork wrap with EFDbContext. Then use DI to inject those dependencies.Then You can get the advantage of Separation of Concerns.
-
Slauma over 12 years@Eranga: Does this mean that the context only gets instantiated if a controller is called which actually takes a context as constructor parameter? For example: If I have a controller with
MyController()
as constructor no context would be instantiated, right? If two controllers get called in one single request (could happen by usingRenderAction
for example) and both controllers have a context as parameter, only one context will be created and injected into both controllers, right? The example above isn't Unity, is it? Do you know if Unity2 offers such a logic too? -
Eranga over 12 years@Slauma yes. DI framework takes care of it. example uses
Autofac
. I have seen "Per request lifetime" implementation ofUnity
on Silk