Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject: Entity Context to Controller

I am aware that a thousand and one questions relating to this topic have been asked, but I have gone through at least a dozen and am still not connecting the dots. I am trying to setup dependency injection for entity contexts.

I have always created my entity context as I have seen in the MS tutorials, like so:

public class UserController : Controller
{
    private DbEntities db = new DbEntities();

}

Recent reading has told me that this is no longer (if it ever was) the best practice, and a dependency injection method should be used. Ninject is mentioned often, but I am seeing how you move from what I have, to the example give in the Ninject documentation.

It should look like this when I am done, right?

public class UserController : Controller
{
    private DbEntities db;

    public UserController(DbEntities context)
    {
        db = context;
    }
}

The documentation starts out with "In the previous step we already prepared anything that is necessary for controller injection." which is confusing as hell, since the previous step was installation. I used the Nuget method to install, but I don't know what it means when it says "Now load your modules or define bindings in RegisterServices method." How do I do that, and is entity a module or a binding? The documentation feels so sparse.

I am sorry if I skipped over something critical in the docs, I've been bouncing between forums for hours trying to figure out this one step.

like image 884
Kyeotic Avatar asked Feb 12 '12 00:02

Kyeotic


2 Answers

I used the Nuget method to install, but I don't know what it means when it says "Now load your modules or define bindings in RegisterServices method." How do I do that, and is entity a module or a binding?

The Nuget installation actually does quite a lot of things for you already. The most important thing is that it sets up Ninject as controller factory, which means that Ninject will create your controllers and is able to pass in all dependencies you have registered with it.

If you check the App_Start folder you will find a file NinjectMVC3.cs. There is already an empty method RegisterServices() which you can use to register your dependencies.

For your example you must be able to resolve DbEntities. The easiest most basic way to do this is:

kernel.Bind<DbEntities>().ToSelf();

That said you really should pass in an interface to your controller so the controller does not depend on Entity Framework, using abstractions and registering a concrete class to use in the IoC container is one of the main reasons for dependency injection.

This should give you a start - the documentation you link to seems a bit outdated. I would recommend looking at the Ninject MVC3 sample on github.

like image 141
BrokenGlass Avatar answered Sep 29 '22 05:09

BrokenGlass


Dependency Injection can seem confusing at first, but it's really actually quite simple.

A Dependency Injection "container" is basically a generic factory, with various object lifetime management features. Ninject, in particular, uses the syntax kernel.Bind() to confgure this factory. When you say kernel.Bind<DbEntities>().ToSelf() this means that Ninject will create an instance of the bound type (DbEntities in this case) whenever that type is requested. This request typically looks like this:

var entities = kernel.Get<DbEntities>();  // Note: don't do this, just an example

At it's core, this is what Dependency Injection is. A generic factory that can instantiate arbitrary types.

However, there is a lot more to it than that. One nice feature of Dependency Injection is that it will also instantiate any dependent types in the process. So, suppose you have a controller, and that controller has a dependency on DbEntities. Well, when a controller is instantiated by the DI Framework, it will also instantiate the dependent DbEntities. See the code below. When the MyController is instantiated, the DbEntities will automatically get instantiated (assuming you have bound the DbEntities class to self in the DI Configuration)

var controller = kernel.Get<MyController>();

public class MyController : Controller {
    private DbEntities _entities;
    public MyController(DbEntities entities) {
        _entities = entities;
    }
}

This is recursive. Any class that gets instantiated that has any objects that it itself might depend on get instantiated as well, and so on, and so on until finally, everything has what it needs to do its job.

Now, the great thing about MVC is that it has a way built-in to use any DI container automatically. You don't have to call kernel.Get because the framework does it for you when it creates the controllers when a request comes in. This feature is called IDependencyResolver, and is an interface that the MVC framework uses to allow third party DI containers to be used by the framework.

If you install Ninject by using the Nuget package Ninject.MVC3 then it will automatically configure all this for you, and you need only add your bindings to the RegisterServices() section of NinjectMVC3.cs

There's a lot more to it than this, but this should give you a basic understanding. Dependency Injection allows you to forget about the details of managing when objects are created and destroyed, you just specify in your constructor which dependencies you need, and assuming you have bindings for them in your configuration, MVC will take care of creating and destroying them for you. You just use them.

EDIT:

To be clear, I don't recommend you use the examples I give above. They are just simple illustrations of how DI works. In particular, the Get() syntax is known as "Service Location" and is considered to be bad. However, ultimately some code, somewhere must call Get(), it's just buried deep in the framework.

As Adam mentions, binding directly to the data entities context isn't a great idea, and you should eventually move to using an interface based approach.

like image 25
Erik Funkenbusch Avatar answered Sep 29 '22 05:09

Erik Funkenbusch