Showing changes from revision #4 to #5: Added | Removed
The Fluent NHibernate AutoMapper is capable of automatically recognising simple components; currently only properties are supported, no relationships inside the 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:
public class Person { public virtual int Id { get; private set; } public virtual string Name { get; set; } public virtual Address Address { get; set; } } 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 with the Fluent Configuration and Database Configuration APIs.
var sessionFactory = Fluently.Configure() .Database(MsSqlConfiguration.MsSql2005 .ConnectionString(c => c .Is(ApplicationConnectionString))) .Mappings(m => m.AutoMappings.Add( AutoPersistenceModel.MapEntitiesFromAssemblyOf<Person>() .Where(type => type.Namespace.EndsWith("Domain")) )) .BuildSessionFactory();
We've now got the auto mappings integrated with NHibernate, so we need to instruct the auto mapper how to identify components; after the Where
call, we can add a call to WithSetup
to help the auto mapper identify our components.
.WithSetup(s => { s.IsComponentType = type => type == typeof(Address); })
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:
Where
does), or checking a suffix on the type name (anything that ends in "Component", for example).Where
call), otherwise they'll be auto-mapped as full entities as well as components - not good.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 type name, so Address.Street
would be mapped against a column called AddressStreet
; 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:
.WithSetup(s => { s.IsComponentType = type => type == typeof(Address); s.GetComponentColumnPrefix = type => type.Name + "_"; })
The convention now specifies that columns should be named TypeName_PropertyName, so Address.Street
is now correctly mapped against Address_Street
.