Fluent NHibernate
Conventions (changes)

Showing changes from revision #1 to #2: Added | Removed

Conventions are small self-contained chunks of behavior that get applied to the mappings Fluent NHibernate generates. These conventions are of varying degrees of granularity, and can be as simple or complex as you require. Fluent NHibernate has a default set of conventions that it uses to generate your mappings, if these choices don't match your design then you can implement your own.

The conventions are built using a set of interfaces that each defines two methods, Accept and Apply, with varying parameters based on the kind of convention you're creating. The Accept method is called in the mapping generation cycle to see if the specific convention implementation wants to be applied to that mapping; returning true in this method will result in your convention being applied to that mapping. Apply is called if your convention is accepted, this is where you actually make the changes to the mappings.

Lets start by implementing a class convention, which gets applied to any ClassMap<T> mappings.

public class LowercaseTableNameConvention : IClassConvention
{
  public bool Accept(IClassMap classMap)
  {
    // acceptance criteria
  }

  public void Apply(IClassMap classMap)
  {
    // alterations
  }
}

This is an empty class convention, you can see the two methods I mentioned. For this example I'm going to make this convention be applied to all class mappings, but you can analyse the IClassMap instance to your hearts extent to determine whether the convention should be applied.

public bool Accept(IClassMap classMap)
{
  return true; // apply to everything
}

Then we need to implement the Apply behavior, again you can use the IClassMap instance but this time you alter it with your conventional changes.

public void Apply(IClassMap classMap)
{
  classMap.WithTable(classMap.EntityType.Name.ToLower());
}

That's Apply implemented, all we're doing is setting the table name to always be lowercase. Simple.

Here's the whole convention:

public class LowercaseTableNameConvention : IClassConvention
{
  public bool Accept(IClassMap classMap)
  {
    return true; // apply to everything
  }

  public void Apply(IClassMap classMap)
  {
    classMap.WithTable(classMap.EntityType.Name.ToLower());
  }
}

Now that we've created our convention, we need to inform Fluent NHibernate of how to use it. The simplest way to do this is just to use the Fluent Configuration mapping setup to use all conventions in an assembly, alternatively you can just add individual conventions. Both these are done through the ConventionDiscovery property of the fluent mappings setup.

Fluently.Configure()
  .Database(/* database config */)
  .Mappings(m =>
  {
    m.FluentMappings
      .AddFromAssemblyOf<Entity>()
      .ConventionDiscovery.AddFromAssemblyOf<LowercaseTableNameConvention>();
  })

Alternatively you can use just Add to add an instance or a type, or you can use the Setup method to call a lambda that can be used to supply multiple different conventions (e.g. some from an assembly, and some individually).

Once you've set that up, Fluent NHibernate will automatically call your convention when it's generating the mappings.

A note on constructors

A convention is required to have either a parameterless constructor (default or not), or a constructor taking a single instance of IConventionFinder; if neither of those constructors exists then the convention will be either ignored (if added through AddFromAssemblyOf<T>) or an exception thrown (if added explicitly). You can read more about the IConventionFinder in Conventions Code.

A note on previous conventions

If you were using our previous conventions API, then you may be interested in Converting To New Style Conventions, which explains the various differences you may encounter; however, there's nothing difficult about it, you just need to pick the right interface. If you're not quite comfortable with this change yet, the Conventions Shortcuts might be of some use.