NCommon with Entity Framework and Unity Example

Jan 31, 2009 at 3:27 PM
Edited Feb 2, 2009 at 6:01 PM
I have successfully set up NCommon with an ASP.NET MVC project using the Entity Framework and Unity IOC container and thought I'd share my settings for others who are trying to do the same.

Note: Updated on 2/2/2009 to simplify ObjectContext creation.

Prerequisites
  1. Download NCommon, Unity, and the UnityServiceLocatorAdapter (found at http://www.codeplex.com/CommonServiceLocator/Wiki/View.aspx?title=Unity%20Adapter&referringTitle=Home )
  2. Compile the UnityServiceLocatorAdapter and reference it in your MVC project.

Global.asax

Here you'll set up the IOC container, register the NCommon types, and set your routes.

        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes); // not shown
            ConfigureUnityContainer();

            // Tell the NCommon EFUnitOfWorkFactory how to get an EF ObjectContext
            EFUnitOfWorkFactory.SetObjectContextProvider(() => new MyObjectContext());

           // Set the controller factory to the Unity factory
            ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(Store.Application.Get<IUnityContainer>("ApplicationContainer")));
        }



        private static void ConfigureUnityContainer()
        {
            // Set up the dependency injection
            IUnityContainer container = new UnityContainer();

            // TODO: Register custom types with container here
        
            // NCommon Types
            container.RegisterType<IUnitOfWorkFactory, EFUnitOfWorkFactory>(new TransientLifetimeManager());
            container.RegisterType(typeof(IRepository<>), typeof(EFRepository<>));

            // Force the container to use the parameterless constructor for EFRepository<>
container.Configure<InjectedMembers>().ConfigureInjectionFor(typeof(EFRepository<>), new InjectionConstructor(new object[] { }));

            
           // Store the container in the ApplicationStore and tell the ServiceLocator how to access it
            Store.Application.Set("ApplicationContainer", container);
            ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Store.Application.Get<IUnityContainer>("ApplicationContainer")));

        }

You'll also need the following class to create the controllers:

UnityControllerFactory.cs
    public class UnityControllerFactory : DefaultControllerFactory
    {
        private readonly IUnityContainer container;

        public UnityControllerFactory(IUnityContainer container)
        {
           this.container = container;
        }


        protected override IController GetControllerInstance(Type controllerType)
        {
if (controllerType == null) return null;
            return (IController)container.Resolve(controllerType);
        }
    }
Coordinator
Jan 31, 2009 at 8:29 PM
`Citezein:

Is there a reason why GetObjectContext() is using the container to resolve the current ObjectContext? Instead of resolving the current ObjectContext via the container you could simply return new MyEntityContext. Unless you are required to share the same ObjectContext per request the idea of using the container to resolve the current ObjectContext is not required.

Also, regarding disposing off the ObjectContext, when you are using NCommon's unit of work, after the unit of work is completed and disposed off the underlying ObjectContext being used by the EFUnitOfWork is also disposed. The ObjectContext would be disposed off whether you are using UnitOfWork or UnitOfWorkScope.

Great work by the way. I'll add a link to the docs to this topic.

Thanks,
Ritesh
Feb 1, 2009 at 10:15 PM
Good catch regarding the ObjectContext creation. This is just a holdover from my previous implementation, which limited the system to one ObjectContext per HttpRequest. Instead of needing the registration of ObjectContext in the Unity container, and the GetObjectContext method, the code can simply be changed to:

EFUnitOfWorkFactory.SetObjectContextProvider(() => new MyEntityContext());
Feb 2, 2009 at 6:02 PM
Edited Feb 2, 2009 at 6:05 PM
I've updated my first post with the simplified code. In addition to changing the ObjectContext creation code, I found I had to add a line of code informing Unity to only use the parameterless constructor for the EFRepository<TEntity> class.