2

The HBM export function in Fluent NHibernate does not seem to work.

If I call FluentMappingsContainer.ExportTo, the generated mappings come out incorrect, and I get the following exception:

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

My configuration code looks like this:

        MsSqlConfiguration database = MsSqlConfiguration.MsSql2008
            .ConnectionString(GetConnectionString())
            .Cache(c => c
                            .UseQueryCache()
                            .UseSecondLevelCache()
                            .ProviderClass<SysCacheProvider>()
            );

        database.ShowSql();

        FluentConfiguration config = Fluently.Configure()
            .Database(database)
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Entity>()
                               .Conventions.AddFromAssemblyOf<Entity>());

        config.ExposeConfiguration(x =>
        {
            x.SetProperty("hbm2ddl.keywords", "auto-quote");
            x.SetInterceptor(new ServiceInterceptor());
        });

        config.ExposeConfiguration(x => { x.SetProperty("current_session_context_class", "thread_static"); });

        // Configure HBM export path, if configured:

        var path = Service.Config.HbmExportPath;

        if (!String.IsNullOrEmpty(path))
            config.Mappings(m => m.FluentMappings.ExportTo(path));

        // Build session factory:

        _sessionFactory = config.BuildSessionFactory();

Setting HbmExportPath in my configuration to null, app launches and runs without problems. As soon as I configure the export path (causing ExportTo to be called), the generated mappings cause an exception as described above.

Looking at the exported mappings, it appears my conventions are not being applied - for example, I have a foreign-key convention in place, using camel-case and "Id" suffix, but when I export the HBM files, primary keys are consistently named with an underscore and lowercase "_id", for example:

<class xmlns="urn:nhibernate-mapping-2.2" name="MyApp.Entities.Contact, MyApp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Contact`">
  ...
  <bag name="Departments" table="ContactDepartment">
    <key>
      <column name="Contact_id" />
    </key>
    <many-to-many class="MyApp.Entities.Department, MyApp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
      <column name="Department_id" />
    </many-to-many>
  </bag>
  ...
</class>

I had this problem with the previous version and with the current release of Fluent.

Any ideas?

mindplay.dk
  • 7,085
  • 3
  • 44
  • 54

1 Answers1

3

After drilling through the Fluent source code (latest from Git repository), something looks odd to me.

The ExportTo() methods are defined twice - once by FluentConfiguration itself, and it does appear it's exporting the configuration files "too soon", resulting in an incomplete configuration, both at run-time (resulting in the above exception) and at export-time.

Oddly, the PersistenceModel type does have the capability to export the complete configuration, but this feature is not exposed. Instead, there are at least two other seemingly broken implementations of ExportTo().

To solve the problem, we need access to the PersistenceModel instance, which has the capability to write the complete configuration - fortunately, I found a way to do that:

        // create a local instance of the PersistenceModel type:
        PersistenceModel model = new PersistenceModel();

        FluentConfiguration config = Fluently.Configure()
            .Database(database)
            .Mappings(m => m.UsePersistenceModel(model) // use the local instance!
                               .FluentMappings.AddFromAssemblyOf<Entity>()
                               .Conventions.AddFromAssemblyOf<Entity>());

        // ...

        var path = Service.Config.HbmExportPath;

        _sessionFactory = config.BuildSessionFactory(); // completes the configuration

        // now write out the full mappings from the PersistenceModel:

        if (!String.IsNullOrEmpty(path))
            model.WriteMappingsTo(path);

The HBM files are now being output correctly!

mindplay.dk
  • 7,085
  • 3
  • 44
  • 54
  • The author (James Gregory) confirmed that this feature is rough and needs some work. So this work-around is the way to go for now - I'm closing this thread, and hope this answer is useful to somebody else. – mindplay.dk Dec 14 '11 at 02:36
  • thanks, I just started looked at some exported hbm.xml files and I thought I was going crazy wondering why my table naming convention was missing. This solved my problems! – dotjoe Mar 12 '12 at 21:59