Site Loading

Autofac and Fluent NHibernate

I have started using Autofac in my personal projects and I must say I love working with it.  It is really simple to add to project and just works.  I have decided to add a post on how to integrate NHibernate with Autofac since I think there may be someone who might need a helping hand on how to integrate them.

I have added a working example of this on my Github account.  This can be found at: https://github.com/Stevevaubell/AutofacExample.

In the solution I have included all the references using Nuget.

 

Setting up the Environment:

  1. Go to nuget and Add the Autofac ASP.NET MVC 5.1 Integration package.
  2. Add a class Called DependancySetup in your project and add the following code:
    public void AddDependencies(IContainer context, string connectionString)
    {
        Contract.Requires(context != null);
        Contract.Requires(connectionString != null);SessionSetup sessionSetup = new SessionSetup(connectionString);
        var sessionFactory = sessionSetup.GetSessionFactory();
    
        var builder = new ContainerBuilder();
    
        builder.RegisterInstance(sessionFactory);
    
        // Either use a session in view model or per instance depending on the context.
        if (HttpContext.Current != null)
        {
            builder.Register(s => s.Resolve().OpenSession()).InstancePerHttpRequest();
        }
        else
        {
            builder.Register(s => s.Resolve().OpenSession());
        }
    
        AddServices(builder);
        builder.RegisterFilterProvider();
        builder.Update(context);
    }
    private static void AddServices(ContainerBuilder builder)
    {
        var serviceAssembly = Assembly.GetAssembly(typeof(DataService));
        builder.RegisterAssemblyTypes(serviceAssembly)
            .Where(t => t.Name.EndsWith("Service"))
            .AsImplementedInterfaces()
            .PropertiesAutowired();
    }
    
    

    The point of this class is to resolve all objects that will be used by our controllers. This includes the set up of our NHibernate session. In the solution I have used Services as a way of querying the database. This is setup in the RegisterAssemblyTypes where the class name ends with service. In this way if I decide to add more services I wont need to add any more configuration, it will just work. The term for this is Convention over Configuration. This means that instead of registering each type we have a convention that will work in the rules set up. The alternative is registering each type: builder.RegisterType().As().PropertiesAutowired();

  3. Add another class called SessionSetup:
    private readonly IPersistenceConfigurer _persistenceConfigurer;
    private SchemaExport _schemaExport;public SessionSetup(string connectionString)
    {
        _persistenceConfigurer = MsSqlConfiguration.MsSql2012
            .ConnectionString(connectionString)
            .AdoNetBatchSize(10);
    }
    
    public SessionSetup(IPersistenceConfigurer persistenceConfigurer)
    {
        _persistenceConfigurer = persistenceConfigurer;
    }
    
    public ISessionFactory GetSessionFactory()
    {
        return Fluently.Configure()
            .Database(_persistenceConfigurer)
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Contact>())
            .BuildSessionFactory();
    }
    
    public void BuildSchema(ISession session)
    {
        _schemaExport.Execute(true, true, false, session.Connection, null);
    }
    

    The point of this class is to set up the connection to the database. The way this works is that the class will look for the Assembly that contains the mapping for the Contact object and add all the mappings it can find.
    The configuration above is for Microsoft Sql Server but this can be changed to be MySql by changing the following line:

    _persistenceConfigurer = MsSqlConfiguration.MsSql2012
                                        .ConnectionString(connectionString)
                                        .AdoNetBatchSize(10);
    

    To:

    _persistenceConfigurer = MySQLConfiguration.Standard
                                        .ConnectionString(connectionString)
                                        .AdoNetBatchSize(10);
    
  4. Once this has been set up all we need to do is add the relevant config into our Global.asax so that when the application loads everything will work. To do this add the following code into the code file:

    var dependencyBuilder = new DependencySetup();
    var builder = new ContainerBuilder();
    builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
    var container = builder.Build();
    dependencyBuilder.AddDependencies(container, ConfigurationManager.ConnectionStrings["Example"].ConnectionString);
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    

    This will create the setup as well as register the controllers for Dependency injection and should just work.

If you need the link to the working example it can be found at: https://github.com/Stevevaubell/AutofacExample.
I hope this has been useful. Good luck!

Close