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 frankly 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.
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 lets create Ninject module:
public class InjectModule : NinjectModule { public override void Load() { } }
Modules like that one are used by Ninject in following way:
var kernel = new StandardKernel(); kernel.Load<InjectModule>();
Depending of where you are starting Ninject container it can look a little different 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:
Bind(typeof(IRepository<>)).To(typeof(Repository<>)); Bind<IUnitOfWork>().To<UnitOfWork>();
Isn’t that cleaner than Unity syntax? Next we need to register EF context class. It is as simple as:
Bind<DbContext>().To<DBEntities>();
Of course 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 including spawned threads. Or for Web apps it could be better to use InRequestScope
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:
Bind<IObjectSetFactory, IObjectContext>() .ToMethod(con =>con.Kernel.Get<DbContextAdapter>());
Whole module for configuration of EF will looks like this:
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.
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 helpful during maintaining of the code.
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 🙂