views:

160

answers:

2

My web app solution consists of 3 projects:

  1. Web App (ASP.NET MVC)
  2. Business Logic Layer (Class Library)
  3. Database Layer (Entity Framework)

I want to use Ninject to manage the lifetime of the DataContext generated by the Entity Framework in the Database Layer.

The Business Logic layer consists of classes which reference repositories (located in the database layer) and my ASP.NET MVC app references the business logic layer's service classes to run code. Each repository creates an instance of the MyDataContext object from the Entity Framework

Repository

public class MyRepository
{
     private MyDataContext db;
     public MyRepository
     {
        this.db = new MyDataContext();
     }

     // methods
}

Business Logic Classes

public class BizLogicClass
{
     private MyRepository repos;
     public MyRepository
     {
          this.repos = new MyRepository();
     }

     // do stuff with the repos
}

Will Ninject handle the lifetime of MyDataContext despite the lengthy dependency chain from the Web App to the Data Layer?

+3  A: 

EDIT

I has some problems with it some time ago, but now it seems to work:

Bind<CamelTrapEntities>().To<CamelTrapEntities>().Using<OnePerRequestBehavior>();

Instead of using HttpModule, you can use OnePerRequestBehavior and it will take care of handling context in current request.

EDIT 2

OnePerRequestBehavior needs to be registered in web.config, because it depends on HttpModule too:

In IIS6:

<system.web>
  <httpModules>
    <add name="OnePerRequestModule" type="Ninject.Core.Behavior.OnePerRequestModule, Ninject.Core"/>
  </httpModules>
</system.web> 

With IIS7:

<system.webServer> 
  <modules>
    <add name="OnePerRequestModule" type="Ninject.Core.Behavior.OnePerRequestModule, Ninject.Core"/>
  </modules>
</system.webServer>

PREVIOUS ANSWER

It is your responsibility to dispose context when it is not needed. Most popular way in ASP.NET is to have one ObjectContext per request. I do it by having HttpModule:

public class CamelTrapEntitiesHttpModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += ApplicationBeginRequest;
        application.EndRequest += ApplicationEndRequest;
    }

    private void ApplicationEndRequest(object sender, EventArgs e)
    {
        ((CamelTrapEntities) HttpContext.Current.Items[@"CamelTrapEntities"]).Dispose();
    }

    private static void ApplicationBeginRequest(Object source, EventArgs e)
    {
        HttpContext.Current.Items[@"CamelTrapEntities"] = new CamelTrapEntities();            
    }
}

This is injection rule:

Bind<CamelTrapEntities>().ToMethod(c => (CamelTrapEntities) HttpContext.Current.Items[@"CamelTrapEntities"]);

My Repository takes ObjectContext in constructor:

public Repository(CamelTrapEntities ctx)
{
    _ctx = ctx;
}
LukLed
What does "seems to work" mean?
jfar
@jfar: I check it a few moments ago and calling kernel.Get<> twice gave me the same instance in request. I don't remember exactly what were the problems before, but somehow I decided not to use it. In the meantime I downloaded new sources, but didn't check it until today, so it was propably corrected.
LukLed
+3  A: 

Just want to mention that Autofac with the ASP.Net integration have the request lifetime support built-in. Resolve instances in the RequestContainer and they will be disposed (if implementing IDisposable) at the end of the request.

You should make your classes DI friendly though:

public class MyRepository
{
     private MyDataContext db;
     public MyRepository(MyDataContext context)
     {
        this.db = context;
     }

     // methods
}

public class BizLogicClass
{
     private MyRepository repos;
     public MyRepository(MyRepository repository)
     {
          this.repos = repository;
     }

     // do stuff with the repos
}
Peter Lillevold