4
votes

This question is similar to Configuring Fluent NHibernate from NHibernate config section but I'm still trying to wrap my brain around this and the answer is not sufficient.

I want to make a database-agnostic inventory management application (more as an experiment than anything else). I want to use the Fluent automapper because it seems like a really cool idea if I could get it to work... keeps things nice and generic and kinda forces you to use a pattern.

So, I make a helper class with a SessionFactory creator like so:

    private static ISessionFactory _SessionFactory;

    public static ISessionFactory SessionFactory {
        get {
            if (_SessionFactory == null) {

                var config = new Configuration().Configure();
                _SessionFactory = Fluently.Configure(config)
                    .Mappings (m => m.AutoMappings.Add (AutoMap.AssemblyOf<Machine> ()))
                    .BuildSessionFactory ();
            }
            return _SessionFactory;
        } 
    }

    public static ISession GetSession()
    {
        return SessionFactory.OpenSession();
    }

I make an app.config like so:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
    </configSections>
    <connectionStrings>
        <add name="NHDataModel" connectionString="Data Source=10.10.10.10;Integrated Security=SSPI;Database=Inventory;" />
    </connectionStrings>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
        <session-factory>
            <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
            <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
            <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
            <property name="connection.connection_string_name">NHDataModel</property>
            <property name="show_sql">true</property>
        </session-factory>
    </hibernate-configuration>
</configuration>

The error message I get when I try to generate a session to play with is as follows:

An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.

  * Database was not configured through Database method.

There is no inner exception.

I would think this works, but I would, of course, be wrong. An examination of the config object shows that it has collected the property information in the app config, yet cannot seem to apply it to the fluent Database Method. I have seen examples very similar to this all over the internet, though none matched exactly, so there's lots of room for stupid mistakes.

I'm sure this is a simple thing, but I've been scratching my head over this for hours. Any help would be greatly appreciated. Nhibernate and FluentNhibernate are techs that I've never used before so this has been a steep learning curve.

3
What exactly was your mistake? I'm having the same problem and can not find the solution. Fluently.Configure().Database(... works perfectly, but in Web.config, App.config error appears! - ridermansb
See the accepted answer below. I commented on what was happening. - Jeremy Holovacs
Sorry, my mistake. Had not seen your comment. - ridermansb

3 Answers

4
votes

Your method seems sound; Fluent NHibernate should indeed allow you to start with a Configuration and add to it. Here's the code from the Fluent NHibernate site, which is semantically identical to yours except you're automapping instead of fluently mapping:

var cfg = new NHibernate.Cfg.Configuration();
cfg.Configure(); // read config default style
Fluently.Configure(cfg)
    .Mappings(
      m => m.FluentMappings.AddFromAssemblyOf<Entity>())
    .BuildSessionFactory();

The only major difference I see is that the site's code never explicitly assigns the config object variable to the results of the Configure() method; this would imply that Configure() modifies the instance on which it's called in addition to returning a deep clone of itself (or just itself).

Some things to check: Are you SURE that the version of Fluent you're using references a version of NHibernate that uses the configuration version 2.2? FNH 1.2 targets NH 3.1, while FNH 1.1 targets NH 2.1.2GA. I do not know which configuration versions either of those use, but if they match the NH version then the Configure() method may not be finding the config section matching the ConfigSectionHandler it's using.

2
votes

I think that Keith is right in that you are not actually populating the NHibernate configuration you have into Fluently.Configure, and thus your configuration is basically ignored. I know you may wish to keep these settings in your configuration file, but if you are willing to bypass the configuration file, you can also do

            _SessionFactory = Fluently.Configure(config)
                .Database(MsSqlConfiguration.MsSql2005.ConnectionString("the connection string"))
                .Mappings (m => m.AutoMappings.Add (AutoMap.AssemblyOf<Machine> ()))
                .BuildSessionFactory ();

If you do that, you no longer need <hibernate-configuration> in your configuration file, and it should fix your problem.

2
votes

Well thanks for the sanity check. It turns out that the problem had to do with the automapping configuration, nothing to do with the database at all. The error message was throwing me and causing me to look in the wrong place. I think I will make a note on the Fluent forum that the wrong message is popping up in that scenario, so that other people don't end up spinning their wheels on this.