Notice: The content in this post may be out of date, please refer to the Auto Mapping Components page in the Fluent NHibernate Wiki for the latest version.
I’ve just committed a change that should allow automatic mapping of simple components; by simple, I mean components that just map properties, nothing fancy. I’ll be looking to expand this functionality in the future, but for the time being any kind of relationships aren’t supported within components. With that in mind, I’ll walk through how to automap your components.
Lets imagine this database structure:
table Person ( Id int primary key, Name varchar(200), Address_Number int, Address_Street varchar(100), Address_PostCode varchar(8) )
We want to map that to the following model:
namespace Domain
{
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Address Address { get; set; }
}
}
namespace Domain.Components
{
public class Address
{
public int Number { get; set; }
public string Street { get; set; }
public string PostCode { get; set; }
}
}
With this design, Address is actually a component, which isn’t a full entity, more of a way of providing a clean model to a normalised database structure. I’ll get started by setting up the auto-mapper.
var autoMappings = AutoPersistenceModel
.MapEntitiesFromAssemblyOf<Person>()
.Where(type = type.Namespace.EndsWith("Domain"));
var sessionFactory = new Configuration()
.AddProperty(ConnectionString, ApplicationConnectionString)
.AddAutoMappings(autoMappings)
.BuildSessionFactory();
That’s our auto mappings integrated with NHibernate. Next we need to instruct the auto mapper in how to identify components; after the Where call, we can add a call to WithConvention which is where we’ll give it a hand.
.WithConvention(convention =>
{
convention.IsComponentType =
type => type.Namespace.EndsWith("Domain.Components");
})
The IsComponentType convention is what Fluent NHibernate uses to determine whether a type is one that will be mapped as a component, rather than a full entity.
There are two things you need to know about this convention:
- You can only set this convention once, so you’ll need to use it in a way that allows you to identify multiple component types with it; there are several options to this, including using the namespace (the above example), or checking a suffix on the type name (anything that ends in “Component”, for example).
- This is not an exclusive call, so you need to segregate your component types from your standard entity types (so they’ll be excluded by the
Wherecall), otherwise they’ll be auto-mapped as full entities as well as components – not good. I’ve done that in this example by separating components into their own namespace.
With that, the Address should now be automatically mapped as a component; the auto mapper will pick up the three properties and map them as properties on the component.
There’s one more thing, for illustrative purposes I’ve deliberately gone against Fluent NHibernate’s inbuilt convention for naming columns. By default any columns mapped in a convention will be prefixed with their property name, so person.HomeAddress.Street would be mapped against a column called HomeAddressStreet; this is my personal preference, but not what our database contains! We can control how our columns are named by altering the GetComponentColumnPrefix convention, like so:
.WithConvention(convention =>
{
convention.IsComponentType =
type => type == typeof(Address);
convention.GetComponentColumnPrefix =
property => property.Name + "_";
})
The convention now specifies that columns should be named ComponentPropertyName_PropertyName, so person.Address.Street is now correctly mapped against Address_Street.
Magic.
Update:
I’ve updated this post to reflect some recent changes whereby the GetComponentColumnPrefix convention was updated to use the component property instead of the component type. This is to allow for multiple component properties on an entity that are of the same type. If you still need to use the type you can access it through the PropertyInfo parameter.

Comments...
Oh man, this make my blog post from yesterday more or less outdated! I can’t keep up with the pace of change!
By Harry M — 1 Jan, 2009 @ 6:17 pm
Note to self: Develop slower!
By James Gregory — 1 Jan, 2009 @ 6:19 pm
Very cool! Keep up the good work. I’m loving Fluent NHibernate
By Hadi Hariri — 1 Jan, 2009 @ 6:25 pm
I am probably missing something here, but Auto Mapping seems to be more trouble and more bug-prone than simply mapping your model field by field. I don’t like the idea of depending on how people name things to be sure that my app still works. In which scenario does auto mapping really shine?
By Wookie — 1 Jan, 2009 @ 6:29 pm
@Wookie: If you’re having trouble, drop us a line on the mailing list. There are many happy customers of auto mapping, so I’m curious as to how you’ve drawn this conclusion.
Auto Mapping is all about conventions, if your application lacks consistent conventions then it isn’t for you; however, I’d also raise the question as to _why_ you don’t have any consistency. Auto Mapping loves a consistent application, and if you have one, Auto Mapping will be easy.
By James Gregory — 1 Jan, 2009 @ 6:34 pm
Thanks for the reply James. I work on a huge product (version 12.5!), hundreds of tables and an heterogeneous codebase, that’s the mindset my question comes from. But there is still hope that sometime in the next couple of years I will have the joy of working on a green- or green-tending-t0-brownfield app again..
I am a newcomer to both NH and Fluent NH, so maybe I am worrying about stuff out of my league, anyway. I tried Fluent NH and Linq2NH this weekend for the first time and it was a great experience.
By Wookie — 1 Jan, 2009 @ 6:41 pm
@Wookie: In that case, Auto Mapping may not be well suited. However, you could use a combination of Auto Mapping and standard mappings if all your new work is consistent.
Auto Mapping is well suited to greenfield applications, but not impossible to use against brownfield apps, depending on what state they’re in; if there’s some kind of consistency, there’s a chance you can auto map it.
It’s definitely a case of right tool for the right job though, so if your application is in a state that doesn’t lend itself to auto mapping, by all means don’t use it.
If you ever have any questions, drop us a line on the mailing list.
http://groups.google.com/group/fluent-nhibernate
By James Gregory — 1 Jan, 2009 @ 6:48 pm
how do you deal with the situation where you have e.g. two addresses for the Person entity: a home address and a work address? How can you prefix the field names with e.g. the property name (that is “HomeAddressStreet” and “WorkAddressStreet”)?
By Gabriel Schenker — 1 Jan, 2009 @ 7:06 am
@Gabriel: Good question! Currently not possible. I guess I’ll need to amend the convention to pass in the property info too.
By James Gregory — 1 Jan, 2009 @ 10:43 pm
James,
Is there anyway to alter the mapping of the component? Where I’m trying to use my component it’s not a perfect name to name match.
I tried:
.ForTypesThatDeriveFrom(autoMap =>
{
autoMap.Map(p => p.Street, “Address”);
autoMap.Map(p => p.State, “Region”);
})
Where Address is my component but I think that makes AutoMap believe it’s a regular object instead of a component.
By Chris Marisic — 1 Jan, 2009 @ 8:21 pm
You probably need to use autoMap.Component rather than Map for Address, as map just creates a property.
By James Gregory — 1 Jan, 2009 @ 8:33 pm
I recently jumped back into NHibernate (after long hiatus) seeing alot of good chatter in the various blogs regarding Fluent NHibernate. I have also started looking into SharpArchitecture, and your series of posts have been very timely. With the ability to use AutoPersistenceModel and AutoMap together along with Sharp’s code generation templates (tt) is a very powerful combination.
Thanks again for your posts!!
By mike kidder — 2 Feb, 2009 @ 12:33 am
I’ve a need for multiple references to a component “Measurement”. Have you implemented this change you mention here?
BR
Charles
“James Gregory wrote:
@Gabriel: Good question! Currently not possible. I guess I’ll need to amend the convention to pass in the property info too.
Posted 20 Jan 2009 at 10:43 pm ¶ “
By Charles — 7 Jul, 2009 @ 8:39 am
Oops. I see your addendum above….
jagregory says “done”….
By Charles — 7 Jul, 2009 @ 8:41 am
Post a comment...