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.
Could you add a configuration within the spring xml file?
What exactly do you mean by that?
I guess what he meant was, what should you add to spring’s configuration file, in order to use this class.
Updated to the most current version of Fluent and this no longer works. Arg.
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.
Thanks for the update.
You can use the regular .Net way (connectionstrings section) and Spring.Net together. So it’s not a big problem.
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
I’ll look into it, but it’ll be something for next week. Won’t have a computer the following days.
Thanks, Benny! I’ll be interested to see what you come up with.
protected override ISessionFactory NewSessionFactory(Configuration config)())
{
config = Fluently.Configure(config)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf
.BuildConfiguration();
return base.NewSessionFactory(config);
}
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?
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;
///
///
///The mapping assemblies.
public string[] FluentNhibernateMappingAssemblies
{
get { return fluentNhibernateMappingAssemblies; }
set { fluentNhibernateMappingAssemblies = value; }
}
///
///
/// protected override void PostProcessConfiguration(Configuration config) properties;
{
IDictionary
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.
Could you add a configuration within the spring xml file
in your blog?
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;
///
///
///The mapping assemblies.
public string[] FluentNhibernateMappingAssemblies
{
get { return fluentNhibernateMappingAssemblies; }
set { fluentNhibernateMappingAssemblies = value; }
}
///
///
/// 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.
Thanks Benny for this post ! and for people how want the spring configuration file :
Project.Core.NHibernate
[quote]
Project.Core.NHibernate
[/quote]
Could not copy paste xml code… Sorry
Here the spring sample :
http://stackoverflow.com/questions/2049968/configuring-asp-net-mvc-2-with-spring-net-and-fluentnhibernate
Funny that you post a link to stackoverflow with a solution I provided 🙂
An neat submit appropriate there mate . Thanks for submitting .
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