5

I need to inject EF context per request. Is there any way to implement it?

PHeiberg
  • 29,411
  • 6
  • 59
  • 81
SiberianGuy
  • 24,674
  • 56
  • 152
  • 266

3 Answers3

7

Did you check out this excellent blog on DI with Unity and ASP.NET MVC?

Should get you on the right track.

The answer is yes, you can - and the article shows you how.

In short, you create a HttpContextLifetimeManager to handle the "scoping" of your objects. The container "caches" the instance in the HTTP Context.

This is needed because the default life time managers provided by Unity don't cover HTTP Context scoping "off the shelf".

Of course, other DI container's (such as StructureMap - which i use), do.

Here is another (more up to date) article on the same thing, with the "Nerdinner" as the example.

RPM1984
  • 72,246
  • 58
  • 225
  • 350
  • If you see the post that you suggested, there he is doing DI on repository as I suggested and he is encapsulating DataContext at some other place. And then within the repository method that author is getting DataContext from some central location. – Pradeep Oct 10 '10 at 08:09
  • I saw your suggestion, and i agree (i also use Repository/UoW). However, this is not a question on design patterns - it's a question on context-scoping for DI, which im hoping my answer helps with. – RPM1984 Oct 10 '10 at 08:12
  • +1 - Nice suggestions and articles. I like StructureMap's built in way of HttpContext scoping and this goes about the issue the same way. – PHeiberg Oct 10 '10 at 09:52
  • Yep. This single issue is the reason why i choose StructureMap over Unity. HTTP Context scoping should be built into Unity - i have no idea why its not. Should never use singletons for db connections. – RPM1984 Oct 10 '10 at 09:55
  • 1
    It's not built in due to worries about dependencies - if we put the HttpContextLifetime then the the DLL can't be used with the .NET 4.0 client profile. – Chris Tavares Oct 11 '10 at 01:37
  • Yes, that's true. Don't know how StructureMap does this then, as the "Hybrid" option is built into the StructureMap core DLL. – RPM1984 Oct 11 '10 at 02:02
  • Client profile was a bad idea anyway. Why cause additional fragmentation in an already complex development environment, purely for the benefit of saving 20mb in the initial download.. – Morten Mertner Mar 19 '11 at 22:27
  • I've been required to use Unity instead of Ninject and I just wanted to say that Ninject does DI a lot better than Unity. – Umar Farooq Khawaja Aug 13 '13 at 14:49
5

The solution proposed in the Unity Discussion list is to create a child container per request, have that child container create the EF context as ContainerControlledLifetime, then have the child container disposed at the end of the request. By doing so you don't have to create a custom LifetimeManager.

I'm not very familiar with Unity but the principle would be something like this:

Application_BeginRequest(...)
{
  var childContainer = _container.CreateChildContainer();
  HttpContext.Items["container"] = childContainer;
  childContainer.RegisterType<ObjectContext, MyContext>
     (new ContainerControlledLifetimeManager());
}

Application_EndRequest(...)
{
  var container = HttpContext.Items["container"] as IUnityContainer
  if(container != null)
    container.Dispose();
}
PHeiberg
  • 29,411
  • 6
  • 59
  • 81
  • Yeah i've seen this pattern, a similar one was proposed to my scenario in StructureMap (http://stackoverflow.com/questions/3665336/iqueryable-repository-with-structuremap-ioc-how-do-i-implement-idisposable) which you were also involved with. In the end, i didn't need to do this (thankfully, as i dont like the idea of creating DC's in begin/disposing in end). – RPM1984 Oct 10 '10 at 08:58
  • Where does _container come from? I think that I understand the concept of the Child Container, but how do I get the parent at the start of the request? I think that this may help me in a similar situation – RobD Mar 27 '14 at 12:21
  • @RobD - The _container usually is initialized by you during App_Start (initial bootstrapping of the root container). – PHeiberg Mar 27 '14 at 13:16
  • Many Thanks PHeiberg, makes sense now – RobD Mar 27 '14 at 14:08
1

What do you mean by injecting? Do you mean to apply dependency inversion principle on it? If yes then do you ever envisage yourself swapping out your EF context with some other context which adheres to same contract?

To me you should encapsulate EF context somewhere in framework, so that every request gets EF DataContext. Apply DI on your repository. Later on your repositories might have different kind of contexts and you can switch repositories with each other.

Pradeep
  • 3,258
  • 1
  • 23
  • 36