Using Fluent NHibernate in Spring.Net

In order to load the mappings you’ve written using Fluent NHibernate you need to call the extension method “AddMappingsFromAssembly” on the configuration. The “LocalSessionFactoryObject” defined in Spring.Net supports out of the box the loading of .hbm files from an assembly or a location in the file system. Luckily this class can be extended with ease. The code below is all you need to use Fluent NHibernate with Spring.Net, any suggestions for a better name are welcome.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spring.Data.NHibernate;
using FluentNHibernate;
using System.Reflection;
using NHibernate.Cfg;
 
namespace SessionFactories
{
    public class FluentNhibernateLocalSessionFactoryObject
	: LocalSessionFactoryObject
    {
        /// <summary>
        /// Sets the assemblies to load that contain fluent nhibernate mappings.
        /// </summary>
        /// <value>The mapping assemblies.</value>
        public string[] FluentNhibernateMappingAssemblies
        {
            get;
            set;
        }
 
        protected override void PostProcessConfiguration(Configuration config)
        {
            base.PostProcessConfiguration(config);
            if(FluentNhibernateMappingAssemblies != null)
            {
                foreach(string assemblyName in FluentNhibernateMappingAssemblies)
                {
                    config.AddMappingsFromAssembly(Assembly.Load(assemblyName));
                }
            }
        }
    }
}

Update 29 June: please check the comments since a new version brought some changes to this blog post.

20 Replies to “Using Fluent NHibernate in Spring.Net”

  1. I guess what he meant was, what should you add to spring’s configuration file, in order to use this class.

  2. It seems we now need to do Fluent configuration to get this to work:

    protected override void PostProcessConfiguration(Configuration config)
    {
    base.PostProcessConfiguration(config);

    Fluently.Configure(config)
    .Database(MySQLConfiguration.Standard.ConnectionString(
    c => c.FromConnectionStringWithKey(“connectionString”)))
    .Mappings( m => m.FluentMappings
    .AddFromAssemblyOf())
    .BuildSessionFactory();
    }

    Note that the connection string now needs to exposed in the standard .NET way via app.config — it doesn’t seem to be picked up from the Spring.NET NHibernate config XML block.

  3. Actually, it turns out this didn’t quite solve the problem for me. I use Spring.NET transaction attributes in my services, and using Fluently.Configure in the LocalSessionFactoryObject.PostProcessConfiguration appears to break this — I’m not getting back Spring’s ISession implementation (I think), so the transaction attributes aren’t being observed.

    Benny, do you have a solution that works with the most current Fluent update? I found that with the newest version of Fluent, no mappings were loading when I invoked

    config.AddMappingsFromAssembly(Assembly.Load(assemblyName));

    which is why I went to Fluently.Configure in the first place

  4. protected override ISessionFactory NewSessionFactory(Configuration config)
    {
    config = Fluently.Configure(config)
    .Mappings(m => m.FluentMappings.AddFromAssemblyOf())
    .BuildConfiguration();
    return base.NewSessionFactory(config);
    }

  5. I’m working with HibernateDaoSupport and I can’t figure out how to configure Fluent in order to make it work. Anybody could help me?

  6. After several trials and experiments I’ve got slightly improved version: assemblies and properties comes (like show_sql) from Spring context.
    The only hardcoded part remains Database section.
    [quote]
    public class TestNhibernateLocalSessionFactoryObject
    : LocalSessionFactoryObject
    {
    private string[] fluentNhibernateMappingAssemblies;
    ///

    /// Sets the assemblies to load that contain fluent nhibernate mappings.
    ///

    /// The mapping assemblies.
    public string[] FluentNhibernateMappingAssemblies
    {
    get { return fluentNhibernateMappingAssemblies; }
    set { fluentNhibernateMappingAssemblies = value; }
    }

    ///

    /// Fluent configuration.
    ///

    /// protected override void PostProcessConfiguration(Configuration config)
    {
    IDictionary properties;

    base.PostProcessConfiguration(config);

    properties = config.Properties;

    Fluently.Configure(config)
    .Database(
    SQLiteConfiguration
    .Standard
    .ProxyFactoryFactory(properties[“proxyfactory.factory_class”])
    .InMemory
    )
    .Mappings(m =>
    {
    foreach (string assemblyName in fluentNhibernateMappingAssemblies)
    {
    m.HbmMappings
    .AddFromAssembly(Assembly.Load(assemblyName));

    m.FluentMappings
    .AddFromAssembly(Assembly.Load(assemblyName));
    }

    //.ExportTo(@”c:ala”);
    })
    .ExposeConfiguration(x =>
    {
    foreach (var item in x.Properties)
    {
    if (properties.ContainsKey(item.Key))
    {
    properties[item.Key] = item.Value;
    }
    else
    {
    properties.Add(item);
    }
    }
    x.SetProperties(properties);
    })
    .BuildConfiguration();
    }
    }
    [/quote]
    I don’t know why but foreach assemblyName works with field but not with a property.
    Also in my case I have both fluent and xml mappings in the same assembly. If this doesn’t work in other cases then you need to define two separate properties.

  7. After further testing I’ve found that original Benny code almost works. The main change I’ve made is related to loading assemblies (changed API):
    [quote]
    public class TestNhibernateLocalSessionFactoryObject
    : LocalSessionFactoryObject
    {
    private string[] fluentNhibernateMappingAssemblies;
    ///

    /// Sets the assemblies to load that contain fluent nhibernate mappings.
    ///

    /// The mapping assemblies.
    public string[] FluentNhibernateMappingAssemblies
    {
    get { return fluentNhibernateMappingAssemblies; }
    set { fluentNhibernateMappingAssemblies = value; }
    }

    ///

    /// Fluent configuration.
    ///

    /// protected override void PostProcessConfiguration(Configuration config)
    {
    base.PostProcessConfiguration(config);

    Fluently.Configure(config)
    .Mappings(m =>
    {
    foreach (string assemblyName in fluentNhibernateMappingAssemblies)
    {
    m.HbmMappings
    .AddFromAssembly(Assembly.Load(assemblyName));

    m.FluentMappings
    .AddFromAssembly(Assembly.Load(assemblyName));
    }
    })
    .BuildConfiguration();
    }
    }
    [/quote]
    It just works for me. I’ve used FNH build 1.0.0.623.

  8. Thanks Benny for this post ! and for people how want the spring configuration file :

    Project.Core.NHibernate

  9. here is the implementation if you are using FluentNhibernate auto mapping :

    protected override void PostProcessConfiguration(Configuration config)
    {
    base.PostProcessConfiguration(config);

    var autoMappingCfg = new AutoMappingConfiguration();

    var autoMap = AutoMap.AssemblyOf(autoMappingCfg)
    .Conventions.Add(DefaultCascade.All(), DefaultLazy.Never())
    .Conventions.Add()
    .Override(map => { map.IgnoreProperty(i => i.Total); });

    Fluently.Configure(config)
    .Mappings(m => m.AutoMappings.Add(autoMap))
    .BuildConfiguration();
    }

    in outmapping you don’t need to inject FluentNhibernateMappingAssemblies. so configure Sping.Net accordingly

Leave a Reply

Your email address will not be published. Required fields are marked *