Click here to Skip to main content
15,881,413 members
Articles / Programming Languages / C#
Technical Blog

Ninject and Entity Framework

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
6 May 2013CPOL3 min read 27.5K   13   1
Ninject and Entity Framework.

Last time I wrote about problem with testing Entity Framework in Visual Studio 2012. During working on this project I also encounter problems with configuration of Ninject to allow injecting Entity Framework classes from its Patterns extension. To be frank, this was not much a problem then lack of documentation. I just was forced to experiment with Ninject and new-thing-for-me Entity Framework Patterns extension.

So to make world of .NET a little easier I decided to write about my experience.

I started with this documentation for EF extension. It is instruction for someone that decided to use Unity in their project.

There is also link to similar instruction with Ninject IoC container, but its empty. Why authors of this extension decided to include in documentation of their project link to something that is empty eludes me. Oh well, you have to make through with things you have. It should not be hard to translate Unity configuration syntax to its equivalent in Ninject.

C#
public static class CompositionRoot
{

    private static readonly IUnityContainer UnityContainer = new UnityContainer();

    public static IUnityContainer Container { get { return UnityContainer; } }

    public static void RegisterServices()
    {
        // Registering interfaces of Unit Of Work & Generic Repository
        UnityContainer.RegisterType(typeof(IRepository<>), typeof(Repository<>));
        UnityContainer.RegisterType(typeof(IUnitOfWork), typeof(UnitOfWork));

        // Every time we ask for a EF context, we'll pass our own Context.
        UnityContainer.RegisterType(typeof(DbContext), typeof(Context));

        // Tricky part.
        // Your repositories and unit of work must share the same DbContextAdapter,
        // so we register an instance that will always be used
        // on subsequente resolve.
        // Note : you should not use ContainerControlledLifetimeManager when using ASP.NET or MVC
        // and use a per request lifetime manager
        UnityContainer.RegisterInstance(new DbContextAdapter(
                 UnityContainer.Resolve()), new ContainerControlledLifetimeManager());

        UnityContainer.RegisterType(
            new InjectionFactory(con => con.Resolve())
            );

        UnityContainer.RegisterType(
            new InjectionFactory(con => con.Resolve())
            );
    }
}

As you can see it is a little convoluted. That is one of reasons why I like Ninject more. It is cleaner.

Oh right. First let's create Ninject module:

C#
public class InjectModule : NinjectModule
{
    public override void Load()
    {
       
    }
}

Modules like that one are used by Ninject in following way:

C#
var kernel = new StandardKernel();
kernel.Load<InjectModule>();

Depending of where you are starting Ninject container it can look a little diffrent but idea is the same you are using modules for registering packs of types. Using that I created module for EF in EF assembly and that way it can be shared in my tests, services, console applications etc.

Now lets fill this new module with meaningful code. Firstly we will register repository and unit of work interfaces:

C#
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
Bind<IUnitOfWork&gt().To<UnitOfWork&gt();

Isn't that cleaner than Unity syntax? Next we need to register EF context class. It is as simple as:

C#
Bind<DbContext>().To<DBEntities>();

Ofcourse DBEntities is your type of EF context class.

Now the harder part, a Unity 'tricky' registering of DBContextAdapter class. What we trying to do here is to make every instance of Repository and UnitOfWork, that is created by Ninject and is transient, created whenever necessary and then disposed, had to share same instance of DBContextAdapter. I decided to make this class single for thread scope. It is not ideal but is bult-in behavior of Ninject. In best case it should be shared for our whole application inlcuding spawned threads. Or for Web apps it could be better to use InRequestScope

C#
Bind<DbContextAdapter>().To<DbContextAdapter>().InThreadScope();

To bind interfaces used by UnitOfWork an Repository classes, which allow them use context class indirectly through shared DBContextAdapter class, we have to bind those interfaces to shared instance of this class. To do that we register interfaces IObjectSetFactory (used by repository) and IObjectContext (used by UnitOfWork) with custom method that returns DBContextAdapter:

C#
Bind<IObjectSetFactory, IObjectContext>().ToMethod(
           con =>con.Kernel.Get<DbContextAdapter>());

Whole module for configuration of EF will looks like this:

C#
public class EFModule : NinjectModule
{
    public override void Load()
    {
        Bind(typeof(IRepository<>))    .To(typeof(Repository<>));
        Bind<IUnitOfWork>().To<UnitOfWork>();
        Bind<UnitOfWork>().ToSelf();
        Bind<DbContext>().To<DBEntities>();
        Bind<DbContextAdapter>().To<DbContextAdapter>().InThreadScope();
        Bind<IObjectSetFactory, IObjectContext>()
            .ToMethod(con =>con.Kernel.Get<DbContextAdapter>());
    }
}

This is sufficient to make EF with Patterns extension working in our application.

C#
this.kernel = new StandardKernel();
kernel.Load();
repository = kernel.Get<IRepository>();

var uow = kernel.Get<IUnitOfWork>();
repository.Insert(new Enity{});
uow.Commit();

This is it. Operation with UoW and repository pattern should work with EF.

Personally I am unhappy that this particular implementation of UnitOfWork does not implement IDisposable interface. This would greatly improve clarity of code as would be helpfull during maintaining of the code.

C#
this.kernel = new StandardKernel();
kernel.Load();
repository = kernel.Get<IRepository>();

using(var uow = kernel.Get<IUnitOfWork>())
{
    repository.Insert(new Enity{});
    uow.Commit();
}

But you can't have everything Smile

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Poland Poland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
GregoryW2-Sep-13 20:50
GregoryW2-Sep-13 20:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.