What’s been happening in Fluent NHibernate land?

Cross-posted to Los Techies

Fluent NHibernate has seen a flurry of development followed by a complete lack of commits, I figure it’s time to let everyone know what’s going on.

The Short Version

We’re rewriting the internals. We have 100% of tests passing, but still can’t guarantee no regressions. Stuff may break, if it does, tell us. It’ll be worth it.

The Long Version

Once upon a time…

Fluent NHibernate at it’s core is a fluent interface over xml generation. We use the series of methods you call in your mappings to build up an in-memory hbm xml document that we then feed to NHibernate. Slowly, as we’ve started to support more and more of NHibernate’s features, we’ve started to find flaws in our architecture. It amounts to us not having enough separation of concerns; our fluent interface is generating xml, I think most people would say that’s not a good thing. Our xml is being generated too soon in the cycle to allow us to do more clever things that’d improve the user’s experience. That’s where the quiet time comes in.

Paul Batum undertook the task of redesigning the internals of Fluent NHibernate to be something much more scalable. I’ll leave the details out for now (maybe a future post), but it amounts to a intermediary layer being introduced between the fluent interface and the xml generation. We’ve dubbed this the Semantic Model, and it’s that which is now generated by the fluent interface, then later translated into xml. This added abstraction allows us to do things that weren’t possible while we were just generating straight xml.

Whilst you wont see any immediate improvements while everything is being converted, the extra layer allows us to inspect the model before it is converted to xml; this gives us some immense capabilities, such as allowing subclasses to be separate from their parent mapping, create reusable component mappings, improve relationship support etc… We’re pretty much limited only by what we can imagine now, rather than by architectural decisions.

However, we have a dilemma. The semantic-model branch has deviated so much from trunk we’ve got a major merge problem. A merge is pretty much out of the question actually, because there’s barely any commonality between the two streams at all. It was then assumed that the branch would eventually replace trunk (we’d just rename trunk to a tag, then rename the semantic-model branch to trunk), and all we needed to do was get the branch up-to-date with the features of trunk. Little did we realise we were essentially committing to something that I typically oppose, a complete rewrite! I’ve never been in a situation where that’s ever been a good idea, and yet here we are, responsible for our own destiny as it was, and we’d chosen a rewrite!

A few weeks went by with very little work happening. I think we’d all started feeling demoralised by the idea of re-implementing most of the features from trunk using the new design. It was a worthwhile endeavor, definitely, but just very uninteresting. We repeatedly swore that we’d get this done, but all the while we felt less inclined to support trunk because every new feature meant a new feature to port too. We stopped.

At that point Hudson Akridge, our newest contributor, had the balls to tell me that he thought what we were doing felt pretty futile. At that moment I gained a great deal of respect for him, as it’s something that was in the back of my mind for some time but I wasn’t ready to face yet. It was that which got me moving again.

I sat down over a long weekend and took on the mammoth task of merging our rewrite branch and trunk, with the aim of allowing the existing code to exist alongside the new code; this approach, if it worked, would allow us to convert existing features at our own pace while still writing new features for the cleaner codebase. After a lot of unpleasant hacking of nice code, I managed to get all our existing tests passing while utilising the semantic model behind the scenes. Our old code still directly generates xml, which then gets injected into the semantic model via a nasty shortcut. It feels dirty, because I’ve had to comprimise some good code to get it working, but in a way I think that’s a good thing; if code is nasty, we’re all less likely to be content with it. The main goal was achieved though, and that was to allow us to work at our own pace on trunk.

Where we stand now is three branches, trunk, integration, and semantic-model. Over the next day or so I am going to merge integration with trunk, which will mean the semantic model will be in use for new features. From there we can slowly migrate all the original code to use our new semantic model, all the while adding new features using it, then eventually remove the duct-tape that’s holding the legacy code to the new code and dump the old stuff.

This is where I’ll give you a little warning: although we have 100% of tests passing, we don’t have 100% coverage. There may be some regressions that we aren’t aware of. If anyone finds anything broken that was working before, contact us immediately on the mailing list or via the issues list and we’ll correct it. Regressions will be treated with the highest priority over any other work.

That’s it, you now know more about what’s happening with Fluent NHibernate than you ever wanted to. I hope this sheds a little light onto what’s been happening with us, and perhaps why your patch hasn’t been applied as quickly as you would’ve liked.

I’m a Los Techie

Just to let anyone know that hasn’t heard by other means, I’m now blogging at Los Techies. I’m going to cross-post between these two blogs, so there’s no need to update your feeds if you’re too lazy; but if you’re already subscribing to the Los Techies general feed then you’ll now get me too.

You can find my blog at: jagregory.lostechies.com

Fluent NHibernate usage stats

Just been totting up some figures on how Fluent NHibernate is doing, thought I’d share them with anyone that’s interested.

These are very rough figures, generated with no scientific consistency, some are cumulative and others are based just on the last full month. They’re more just to satisfy my curiosity than to be rigorously accurate.

Downloads 1,800 per month
Unique visitors 5,500 per month
Page views 13,000 per month
Mailing list messages 450 per month
Commits 45 per month

Something else that’s interesting is of those 5,500 visitors/13,000 page views, 66% are coming directly from google, 4% directly, then the other 30% from referrers. Those referrers are broken down into (from highest to lowest): Stack Overflow, my blog, pnpguidance.net, nhforge, then quite a few other sites forming the lower percentages. I’m surprised at how high Stack Overflow is, I guess it pays that I pay attention to questions asked about Fluent on there.

Those download numbers are probably not representative either as they’re only of the zip files, while I believe the vast majority of people run off the trunk through Subversion, so it’s hard to count them.

Docu + 2 days

It’s been two days since I announced docu, my simple documentation generator for .Net apps.

The reception it’s received has been positive, I never expected it to have a surge of popularity because it’s not that kind of tool, so it hasn’t come as much of a surprise that people haven’t been jumping all over it. Having said that though, I have had some good feedback and already someone has contributed a patch. Additionally, there hasn’t been one question as to why I’ve created it; now this has come as a surprise, I guess I’m not the only one that feels Sandcastle is bloated and overcomplicated. Yay!

I’ve just pushed out some changes to the github repos and released an updated alpha (v0.1.0.2) on the downloads page. The biggest changes so far are the inclusion of events and fields in the parsing, which now means docu has <summary /> support for all documentable members. The rest of the changes are mainly refactorings and some battle-hardening.

I’ve got some more changes and several issues lined up, so keep an eye out.

Introducing Docu - Simple doc gen for .Net

Lets look at a recent Twitter conversation of mine:

  • Anyone have any tips on generating html docs from XML comments? Used to do it years ago with NDoc ?
  • Man, sandcastle is so overly complex ?
  • Sandcastle examples don’t even work. This is shit. ?
  • Why isn’t sandcastle just a console app that takes a list of dlls and spits out html/chm? What’s with all the batch files and XslTransforms? ?
  • @AndrewNStewart Well Sandcastle requires chaining together several calls to 3+ applications before you get anything. ?
  • Are these Sandcastle generated MSDN-style API docs actually useful to anyone? ?
  • @pollingj It’s a dilemma. I don’t care about API docs, but people seem to want it, but I’m reluctant to generate msdn-like shit. Dilemma. ?

So as you can see, dilemma. People want API documentation (for Fluent NHibernate specifically), but I don’t want to associate myself with the awful MSDN-style documentation that’s produced by Sandcastle.

Before you get all hot under the collar, if you like Sandcastle, or you like MSDN-style documentation, leave now. Use what works for you, it doesn’t work for me so I’m not using it, but I don’t want to stop you using it.

I realise the market for this tool is probably pretty small, but it’s useful to me so it might be useful to you.

Introducing docu, the simple documentation generator for .Net!

Docu is a tool that produces an html site (or rather, a collection of html pages) from the doc-comments you include in your code. Given an assembly and the Visual Studio produced XML of the comments, docu will produce a completely static collection of pages that you can publish anywhere you like. You run it through one command-line tool, with one parameter. That’s it, nothing complicated.

docu your-assembly.dll

You can see an example of the default style that’s provided in the Fluent NHibernate API docs (the colour scheme has been modified, but everything else is default).

Docu is completely stand alone, no GAC deployed assemblies, no hard-coded paths, no nothing. This makes it trivial to use docu in your CI process for building up-to-the-second API docs for publishing or downloading.

The templates that docu uses are created with the Spark view engine which means you have all the power of C# and it’s templating language at your finger-tips. If you’re particularly picky about appearance (like I am) then you can completely rewrite the templates to your heart’s content. There’s no imposed structure or style, it’s all customisable through the templates. You can read more about customising templates on the site: customising templates.

An interesting little feature of the templating system is special names for directories and files, for example if you name a template !namespace.spark, a html page will be produced for a each namespace in your assembly using that template. This allows you to do things like create a directory for each namespace, with a page for each type in that namespace inside. Pretty powerful!

The codebase is reasonably well structured, but the code itself is a bit untidy. Luckily it’s covered by nearly 200 unit tests (so far) and i’ll be leveraging them to improve the code quality over time. You can checkout the code from the docu github repo.

It’s early days yet, there’s very little customisation of the documentation process (the part that actually finds the types and members to document), and not all comment types are supported yet; however, it’s used for Fluent NHibernate and works pretty well. It’s only Alpha right now, so you shouldn’t expect the world.

So if this kind-of thing interests you, go have a read of the docu website and let me know how it works out for you.

Fluent NHibernate: Conventions Rewrite

I’ve just committed a rather large update to the Fluent NHibernate conventions code. This post explains why I’ve done this, and gives you some starting points to update your code. Anything else you need can be found on the wiki under conventions and converting to new-style conventions.

So why have I rewritten conventions? Our original implementation was simple, but not really maintainable into the future. It was a single class that was a major violation of separation of concerns, and it just kept growing and growing. It didn’t gracefully degrade either; if we didn’t have the exact convention you needed it was tough luck, there was very little you could do short of modifying the code yourself.

Our original design worked something like this:

.WithConventions(conventions =>
{
  conventions.TableName = type => type.Name + "Table";
  conventions.DefaultLazy = true;
})

As you can see, it’s a fairly simple design. Lambda functions were set that got called in various places throughout the mapping generation cycle. It was a good design for simple scenarios; however, when you start overriding more conventions, and introducing logic into them, it can quickly become a massive ball of mud. So while there was an initial simplicity to it, that simplicity was quickly lost if you were trying to do anything clever with it. This is another thing that the rewrite aims to solve.

So how have things changed? The ability to define conventions inline is gone, for starters. Instead what you have is a series of interfaces of varying degrees of granularity; any classes implementing any of the interfaces will be automagically hooked into the mapping generation cycle. What this equates to is you’ll have a folder/namespace in your projects dedicated to conventions, each class making an alteration to the conventions when it’s called. As each convention is an interface, it means you can implement multiples of them in a single class, which allows you to group common conventions into a single class if you desire.

Example: Customising the table name

public class TableNameConvention : IClassConvention
{
  public bool Accept(IClassMap classMap)
  {
    return true; // apply to all mappings
  }

  public void Apply(IClassMap classMap)
  {
    // will produce table names like: tbl_Customer, tbl_Product
    classMap.WithTable("tbl_" + classMap.EntityType.Name);
  }
}

This is a simple implementation of the IClassConvention interface, which is applied to all class mappings (hence the return true in Accept) and simply prefixes the table name with tbl_.

Example: Adding your conventions

There’s one thing you need to do to get Fluent NHibernate to use your conventions, and that’s to inform the convention discovery mechanism of where it’s to search for conventions. You do this using the PersistenceModels CovnentionFinder property, or through the ConventionDiscovery property through Fluent Configuration.

Fluently.Configure()
  .Mappings(m =>
  {
    m.FluentMappings
      .AddFromAssemblyOf<Entity>()
      .ConventionDiscovery.AddFromAssemblyOf<MyConvention>())
  })

That’s all there is to it really, certainly from a users perspective anyway. The architecture is designed in such a way that you have a much greater control of the granularity of your conventions; if you need a convention we haven’t explicitly supplied, you can use the convention “above” the one you want, and implement it yourself. If you need a convention for just Bag collections (which we don’t have one for), you just need to create an implementation of IHasManyConvention and limit it to bags. Easy.

Some shortcuts

I realise that the new design is more verbose than it was originally, and if your scenario really is one that only uses one or two conventions, then the new design might be too much for you. To cater for you people, I’ve created some basic inline support. I really don’t recommend you use these unless you’re doing something really simple. Separation is always preferred.

There’s the ConventionBuilder class which has several static properties (Class for example, there’s one for each convention) which allow you to create an inline convention.

ConventionBuilder.Class.Always(x => x.SetAttribute("something", "true"))
ConventionBuilder.Id.Always(x => x.ColumnName("ID"))

ConventionBuilder.Property.When(
  x => x.Property.PropertyType == typeof(int),
  x => x.ColumnName(x.Property.Name + "Num")
)

These can be used directly in the ConventionDiscovery property mentioned above; it has an Add method that can take a params array of conventions, there’s also a Setup method which can be used for multiple additions.

.ConventionDiscovery.Add(
  ConventionBuilder.Class.Always(x => x.SetAttribute("something", "true")),
  ConventionBuilder.Id.Always(x => x.ColumnName("ID"))
)

.ConventionDiscovery.Setup(c =>
{
  c.AddFromAssemblyOf<MyConvention>();
  c.Add(ConventionBuilder.Id.Always(x => x.ColumnName("ID")));
})

In addition to that, there’s a limited selection of very common conventions which can be used inline. Again, I don’t advocate using these for anything complicated. If you start having logic in your conventions, or even if the lambdas end up being multi-line, I’d suggest using the full conventions. These helpers live in the FluentNHibernate.Conventions.Helpers namespace.

Table.Is(x => "tbl_" + x.EntityType.Name)
PrimaryKey.Name.Is("ID")
DynamicUpdate.AlwaysTrue()

These can be used in the same way as the ConventionBuilder above.

Regarding auto mapping

The auto mapper uses a small subset of conventions to discover various parts of your mappings. It was originally the case that these special conventions were lumped in with the rest of the conventions, even though you couldn’t use them outside of the automapper. As the old style conventions have gone, the automapper now has a separate set of conventions (they’re the same ones, just moved) that it uses. So in addition to the ConventionDiscovery property, the auto mapper has a WithSetup method that you can use to configure the auto mapping specific ones (IsBaseType primarily).

Further reading

So this post should have given you a basic introduction to the changes I’ve made. To go further, you’re going to have to know what interfaces are available to implement. You should probably also read the general conventions wiki, how to convert your existing conventions to the new style, and the convention shortcuts if it interests you. For maintainers, or just curious people, there’s also the wiki on how the conventions work behind-the-scenes.

Fluent NHibernate: Auto mapping, overrides and alterations

Notice: This is an excerpt from Auto Mapping Overrides and Configuration Alterations on the Fluent NHibernate Wiki. It is recommended you refer to those pages for the latest version of this content, as this blog post will not be maintained for correctness.

When using the Auto Mapping facilities of Fluent NHibernate you can use the ForMappingsThatDeriveFrom method described in Altering Entities to override the mappings for specific entities, but that can quickly become cluttered if you’re having to alter many entities.

An alternative is to use an IAutoMappingOverride<T>, which is an interface you can implement to override the mappings of a particular auto-mapped class.

public class PersonMappingOverride : IAutoMappingOverride<Person>
{
  public void Override(AutoMap<Person> mapping)
  {
  }
}

This example overrides the auto-mapping of a Person entity. Within the Override method you can perform any actions on the mapping that you can in the Fluent Mappings.

To use overrides, you need to instruct your AutoPersistenceModel instance to use them. Typically this would be done in the context of a Fluent Configuration setup, but I’ll just illustrate with the AutoPersistenceModel on it’s own.

AutoPersistenceModel.MapEntitiesFromAssemblyOf<Person>()
  .Where(type => type.Namespace == "Entities")
  .UseOverridesFromAssemblyOf<PersonMappingOverride>();

It’s the UserOverridesFromAssemblyOf<T> call that instructs the AutoPersistenceModel to read any overrides that reside the assembly that contains T.

These overrides are made possible with use of the configuration alteration capabilities of the AutoPersistenceModel. You can use these features yourself to create your own customisations, or simply to separate your configuration into logical sections.

An alteration is an implementation of the IAutoMappingAlteration interface, and is a self contained piece of configuration logic that can be applied with others to an AutoPersistenceModel prior to any mappings being generated. These are simple to use, but very powerful.

public class WhereAlteration : IAutoMappingAlteration
{
  public void Alter(AutoPersistenceModel model)
  {
    model.Where(type => IsMappable(type));
  }

  private bool IsMappable(Type type)
  {
    // some logic
  }
}

The Alter(AutoPersistenceModel model) method is where you place your logic for altering the model, you can do anything in here you like. The overrides functionality, for example, inspects an assembly looking for any IMappingOverride<T> instances and executes each one against the model.

You need to instruct your AutoPersistenceModel to use any alterations you may have, and you do that using the WithAlterations method. Typically this would be done in the context of a FluentConfiguration setup, but I’ll just illustrate with the AutoPersistenceModel on it’s own.

AutoPersistenceModel.MapEntitiesFromAssemblyOf<Person>()
  .WithAlterations(alterations =>
    alterations.AddFromAssemblyOf<WhereAlteration>());

The WithAlterations method takes a lambda action that allows you to set multiple alterations on your model; you can add single alterations with Add, and everything from an assembly like the above example.

Before your mappings are generated, the alterations are all run against the AutoPersistenceModel. There’s currently no ordering of alterations, so you cannot rely on the ability to stack alterations.

Fluent NHibernate - The official website

“Documentation? What documentation!” I hear you say. Yes, Fluent NHibernate is not best known for it’s abundance of documentation. I know.

I’ve realised that over the past couple of months Fluent NHibernate has been growing in popularity, stupidly so. We’ve got new features out the bjingo, an active mailing list, and a flow of people moaning on twitter. Well I figure enough is enough, we need a proper website; googlecode is great for hosting, but it’s wiki is poor, we needed something better.

Announcing the official Fluent NHibernate website: http://fluentnhibernate.org and it’s wiki.

As always, comments are welcome on the mailing list. Please, no porn on the wiki just yet.

I will be updating all my recent blog posts to point to the appropriate content on the wiki, and I would prefer if people would direct-link to the website rather than the googlecode project from now on. We’ll still be using googlecode for hosting and issue tracking, but the wiki will be cleared out.

As with any wiki, the content is not final, and not exhaustive. I’m working on it.

Fluent green and brown

To paint a very black-and-white picture, there are two camps of applications: greenfield and brownfield. Greenfield are generally nice, they have good separation of concerns, probably an IoC container, they may even be covered by unit tests. Brownfield apps are not. They generally don’t have great separation of concerns (they’re usually pretty concerned about everything), they definitely don’t have great unit test coverage (but you’re working on it!), and they don’t have IoC containers.

If you’re designing a framework you need to cater for both these markets. Unfortunately, they’re both at odds with each other. A design that caters for inversion of control can sometimes be too verbose or “bitty” to use easily without a container. Similarly, if designed without a container in mind it will fall short for use with one; it’ll be too tightly nit, too hard to break apart.

Although when Fluent NHibernate was started it was heading towards a design for greenfield, when I took over I steered it in the direction I thought was most important - brownfield. Fluent NHibernate has been aimed at being a drop-in replacement for your traditional NHibernate setup, simply replace your `CreateSessionFactory` method with ours and you’re away. The problem is, by focussing so hard on brownfield, I’ve neglected the green.

I’m not apologising, because nobody has complained, but considerations need to be made for the other half. I still very much believe that Fluent NHibernate is heading in the right direction, we want to make life easier for those people who’s lives are pretty damn hard (those greenfield guys have it easy anyway); however, I do believe considerations need to be made to allow Fluent NHibernate to be more accessible for those of us who have the pleasure of working in a well designed system.

What does the future hold for Fluent NHibernate? Supporting all of NHibernate’s mapping options, making the automapper a lot more powerful, improving testability even more, and finally… giving some love to the PersistenceModel and SessionSource that the greenfield guys need.

Fluent NHibernate: Configuring your application

Notice: The content in this post may be out of date, please refer to the Fluent Configuration page in the Fluent NHibernate Wiki for the latest version.

There’s been a grey area of how to actually configure your application to use Fluent NHibernate, and also how to configure some more complicated situations (such as mixing fluent and non-fluent mappings). After some thought I’ve committed a change that should make things clearer. What follows is a few examples of how this new API can be used.

I’m going to assume that you’ve got an application already set up, or you know how to structure a standard NHibernate application. If you don’t, I suggest you read up on that first.

All the examples that follow are tailored to directly replace your SessionFactory instantiation code.

Introducing the configuration API

You can now Fluently.Configure your application. The API is broken down into five main methods, three of which are required.

Fluently.Configure()
  .Database(/* your database settings */)
  .Mappings(/* your mappings */)
  .ExposeConfiguration(/* alter Configuration */) // optional
  .BuildSessionFactory();

You can combine these methods in various ways to setup your application.

  1. Fluently.Configure starts the configuration process
  2. Database is where you specify your database configuration
  3. Mappings is where you supply which mappings you’re using
  4. ExposeConfiguration is optional, but allows you to alter the raw Configuration object
  5. BuildSessionFactory is the final call, and it creates the NHibernate SessionFactory instance from your configuration.

Exclusively fluent

If you’re in the situation where your application is exclusively using fluent mappings, then this is the configuration for you.

var sessionFactory = Fluently.Configure()
  .Database(SQLiteConfiguration.Standard.InMemory)
  .Mappings(m =>
    m.FluentMappings
      .AddFromAssemblyOf<YourEntity>())
  .BuildSessionFactory();

This setup uses the SQLite database configuration, but you can substitute that with your own; it then adds any fluent mappings from the assebly that contains YourEntity.

Automappings

If you’re using only auto mappings, then this config is for you.

var sessionFactory = Fluently.Configure()
  .Database(SQLiteConfiguration.Standard.InMemory)
  .Mappings(m =>
    m.AutoMappings.Add(
      // your automapping setup here
      AutoPersistenceModel.MapEntitiesFromAssemblyOf<YourEntity>()
        .Where(type => type.Namspace.EndsWith("Entities"))))
  .BuildSessionFactory();

Replace the code inside AutoMappings.Add with your auto mapping configuration. You can see more about auto mappings in my automapping tag.

Mixed fluent mappings and auto mappings

If you’re using a combination of standard fluent mappings and auto mappings, then this example should show you how to get started.

var sessionFactory = Fluently.Configure()
  .Database(SQLiteConfiguration.Standard.InMemory)
  .Mappings(m =>
  {
    m.FluentMappings
      .AddFromAssemblyOf<YourEntity>();

    m.AutoMappings.Add(
      // your automapping setup here
      AutoPersistenceModel.MapEntitiesFromAssemblyOf<YourEntity>()
        .Where(type => type.Namspace.EndsWith("Entities")));
  })
  .BuildSessionFactory();

You can see that this is a combination of the two previous examples, the Mappings method can accept multiple kinds of mappings.

HBM mappings

You’ve not yet got around to using Fluent NHibernate fully, but you are configuring your database with it; this configuration will let you configure your database and add your traditional hbm mappings.

var sessionFactory = Fluently.Configure()
  .Database(SQLiteConfiguration.Standard.InMemory)
  .Mappings(m =>
    m.HbmMappings
      .AddFromAssemblyOf<YourEntity>())
  .BuildSessionFactory();

The HbmMappings property allows you to add HBM XML mappings in a few different ways, this example adds everything from an assembly which defines YourEntity; however, you can add from an assembly instance, or just add single types.

Mixed HBM and fluent mappings

You’re migrating your entities to Fluent NHibernate but haven’t quite got them all across yet - this is for you.

var sessionFactory = Fluently.Configure()
  .Database(SQLiteConfiguration.Standard.InMemory)
  .Mappings(m =>
  {
    m.HbmMappings
      .AddFromAssemblyOf<YourEntity>();

    m.FluentMappings
      .AddFromAssemblyOf<YourEntity>();
  })
  .BuildSessionFactory();

The whole shebang: fluent, auto, and hbm mappings

You’re a crazy fool and map a bit of everything, then this is how you’d configure it.

var sessionFactory = Fluently.Configure()
  .Database(SQLiteConfiguration.Standard.InMemory)
  .Mappings(m =>
  {
    m.HbmMappings
      .AddFromAssemblyOf<YourEntity>();

    m.FluentMappings
      .AddFromAssemblyOf<YourEntity>();

    m.AutoMappings.Add(
      // your automapping setup here
      AutoPersistenceModel.MapEntitiesFromAssemblyOf<YourEntity>()
        .Where(type => type.Namspace.EndsWith("Entities")));
  })
  .BuildSessionFactory();

Exporting hbm.xml mappings

In the Mappings call, you can do the following:

.Mappings(m =>
{
  m.FluentMappings
    .AddFromAssemblyOf<YourEntity>()
    .ExportTo(@"C:\your\export\path");

  m.AutoMappings
    .Add(...)
    .ExportTo(@"C:\your\export\path");
})

That will export all of your fluent and automapped mappings in hbm.xml format to whatever location you specify.

Altering non-automapped conventions

If you want to override conventions that are used by your non-automapped classes, then you can use the AlterConventions method on FluentMappings.

.Mappings(m =>
  m.FluentMappings
    .AddFromAssemblyOf<YourEntity>()
    .AlterConventions(conventions =>
    {
      conventions.IsBaseType =
        type => type == typeof(BaseType);
    }))

Validation

If you forget to setup your database, or don’t add any mappings, instead of pulling out your hair over obscure NHibernate exceptions, the BuildSessionFactory method will throw a more helpful exception to try to point you in the right direction. It’ll tell you whether you’ve forgot to add any entities, or not setup your database.

That’s it for now, I hope this helps to make configuring your application a little clearer.