A couple of people have already covered this already, specifically Bobby Johnson, Matt Hinze, and Zachariah Young. I figure I should say something on it anyway.
I’ve adopted a project from Jeremy Miller that I think has the potential to be a really useful tool. It’s called Fluent NHibernate, and it’s primarily a fluent API for mapping classes with NHibernate.
We’re all well aware how awesome NHibernate is, but I think we all also have a bit of a dislike for the amount of XML you need to write to get your classes mapped; not only that, but also how the mappings are distinctly separate from the rest of your application. They’re often neglected and untested. One of the core tenets of the project is that we need a more succinct, readable, and testable way of writing your mappings.
The API
Take the following simple hbm file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Eg" assembly="Eg">
<class name="Customer" table="Customers">
<id name="ID">
<generator class="identity" />
</id>
<property name="Name" />
<property name="Credit" />
<bag name="Products" table="Products">
<key column="CustomerID"/>
<one-to-many class="Eg.Product, Eg"/>
</bag>
<component name="Address" class="Eg.Address, Eg">
<property name="AddressLine1" />
<property name="AddressLine2" />
<property name="CityName" />
<property name="CountryName" />
</component>
</class>
</hibernate-mapping>
Then compare it to the same mapping, created using the fluent API:
public CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Id(x => x.ID);
Map(x => x.Name);
Map(x => x.Credit);
HasMany<Product>(x => x.Products)
.AsBag();
Component<Address>(x => x.Address, m =>
{
m.Map(x => x.AddressLine1);
m.Map(x => x.AddressLine2);
m.Map(x => x.CityName);
m.Map(x => x.CountryName);
});
}
}
Firstly, you’ll note that there is a marginal reduction in lines of code, but that’s not what we’re particularly striving for. Instead we’re intent on reducing the verbosity and noise of the code. This manifests itself in a convention over configuration design for the API, where we choose the most common setups and use those as the default. For example with the id element in the hbm file, you’re required to specify what the generator type is; however, in our fluent API we check the type of your identity property and decide what generator we should use. Int’s and longs default to identity, while GUIDs use the guid.comb generator. You can change these explicitly, but when you are using the default, it greatly reduces the verbosity of your mapping.
Testability
Another one of our goals is to make your mappings more robust. I imagine most people have had the problem where you’ve renamed a property and not updated the mapping file; due to there being no compile time validation, the only way to catch these mistakes are at run time (hopefully you had tests to cover that!). With the way our API is designed, you use the actual properties on your classes to create the mapping, so there’s nothing to forget. If you rename a property, your IDE will either rename the property in the mapping, or fail at compilation.
We also want to help you verify that your mappings are set up properly, not just syntactically valid. So to make your integration tests a bit easier, we’re providing an API for testing your mappings.
[Test]
public void VerifyCustomerSaves()
{
new PersistenceSpecification<Customer>()
.CheckProperty(x => x.Name, "James Gregory")
.CheckProperty(x => x.Age, 22)
.VerifyTheMappings();
}
Behind the scenes the PersistenceSpecification creates an instance of your entity, then populates it with the values you specify through the CheckProperty method. This entity is then saved to the database, then reloaded through a separate connection. The returned entity is then compared to the one originally saved, and any differences fail the test. It’s a fairly standard integration test, except we’ve taken the time to write all the wiring up that needs to be done, so you don’t have to.
The Framework
We’re working towards our first official release, which will have a fairly solid implementation of the API. Once that’s out in the wild, we’re going to focus on our Framework.
Our framework is a layer that sits on-top of the API to provide an even better experience. We’re looking to integrate with your favorite container, which will reduce the code you need to write to integrate NHibernate into your system. Then we’re going to tackle extensible conventions, which will allow you to specify your own implied conventions for your application. For example, if you’re always going to call your identifier “ID”, then why should you have to specify it every time? You shouldn’t!
Development is progressing at a nice pace, and I expect we’ll be able to get our first release out within the next few weeks. The testing API hasn’t been kept quite as up to date as the main API, but we’re working on that too. It’s open-source, so suggestions and patches are welcome.
Trackbacks...
- Pingback from Fluent NHibernate « Hendry Luk — Sheep in Fence
- Pingback from Willem Meints : Tired of using XML all the time?
- Pingback from Frameworks Open Source para .NET : System.Me
- Pingback from indomitablehef.com » Blog Archive » Fluent NHibernate
- Pingback from Enhancing Team’s Productivity - .NET, VS.NET « Niraj Bhatt - Architect’s Blog
- Pingback from What framework is right for me? - Overclock.net - Overclocking.net
- Pingback from Fluent NHibernate Automapping | All Free For You

Comments...
Really nice!
I’m curious how composite Ids work. If you’d just paste me a quick code sample I’d appreciate it.
By Justin — 8 Aug, 2008 @ 7:38 pm
Unfortunately composite IDs currently aren’t implemented. I’ve created an issue for this and we’ll hopefully get to it soon.
Thanks for the feedback.
By James Gregory — 8 Aug, 2008 @ 7:48 pm
An NHibernate I can get on board with. I’ve purposefully stayed clear thus far (for the most part) because the extra issues that you mention caused by an XML configuration file is more work than just using plain ADO.NET and code-snippets – even with relationships/mappings/etc.
I’m glad someone is recognizing that XML configuration files != better applications
By Brian Johnston — 8 Aug, 2008 @ 11:30 pm
I use object for my Id property and then define the generator to use in the mappings. is there a way to do something like this in the fluent interface like override the default reflection on the property type and force it to use Guid or something?
By Mike — 8 Aug, 2008 @ 3:44 am
Mike: There is a workaround for situations like that. You can use Id(x => x.Id).SetGeneratorClass(“My Class Name”).
Care to describe why you have such a setup? It’s not something we’ve really considered.
By James Gregory — 8 Aug, 2008 @ 11:01 am
For a long time I have explicitly set the type on the Id, often passing in a generic TId for my domain superclass as is so common. (DomainObject)
In my latest project though I was refactoring to use Guid instead of int Ids and I wondered why I needed to define this explictly in my domain since I typically only use the Id for persistence and absolutely no business meaning.
All my persistence access uses object on any Id lookups anyways and I don’t think ( I could be wrong) that I am getting any boxing/unboxing penalties at runtime since NHibernate shouldn’t need to reflect on the class at all to assign the Id with the generator class defined.
It’s not a huge deal but it does seem to be more natural to have the persistence meaning in the persistence layer (NHib) .
So far I haven’t hit a single bump except perhaps a sloppy moment passing in a string representation of a Guid instead of a real Guid (from my ui layer)…but that just means my stupidity is revealed from a lower layer in my app.
I am open for any flaws in my thinking though.
By Mike — 8 Aug, 2008 @ 9:44 pm
That’s an admirable goal, I’ve just never really seen it attempted before.
From my point of view, your domain is already compromised by having the ID in there, so having the type doesn’t make matters any worse, and it’s a bit easier for the developer. If it works for you though, that’s great.
Do you explicitly set the Id type in the mapping then? I imagine NHibernate wouldn’t be able to guess what the type should be.
By James Gregory — 8 Aug, 2008 @ 9:51 pm
Actually, I do specify the type of the Id tag in an hbm.xml typically so there isn’t any guessing on NH’s part. I wasn’t so much trying to purify my domain as I was trying to minimize the amount of code touching I had to do if I change my Id strategy. I realize such an abrupt change shouldn’t happen with better planning but since I did it I havent’ heard a reason why not to just use plain ole ‘object’ for Id and let NH do the work for me.
By Mike — 8 Aug, 2008 @ 10:09 pm
Great to see that it is possible to use NHibernate without having to write all those mapping files. It’s especially great since it prevents all those pesky runtime errors. Also users can’t mess up your application when you use this. I am aware of the embedded resource trick, but I don’t like that solution as much as this one.
By W.Meints — 8 Aug, 2008 @ 8:13 am
Last thing I read about using GUID’s for keys, is that it’s a bad idea, performance-wise, as they fuck up physical key clustering distribution, which at it’s turn, is essential to a performing database.
But I could be wrong
By Grimace of Despair — 8 Aug, 2008 @ 9:19 am
Two words. “You rock!”
By Joe Ocampo — 8 Aug, 2008 @ 6:58 am
Wondering why nobody mentioned using attributes for mapping, rather than XML. That’s what we do and it works out great and is pretty readable.
By Winston Fassett — 8 Aug, 2008 @ 9:22 pm
Winston: I’m not keen on the mapping attributes, because they pollute your domain model with persistence concerns. If they work for you though, that’s great.
By James Gregory — 8 Aug, 2008 @ 7:52 am
One small concern. There’s a guideline for calling virtual methods in constructors. Basically don’t do it:
http://blogs.msdn.com/brada/archive/2004/08/12/213951.aspx
It’s too late in the morning for me to work through the implications of this, but Resharper threw this warning at me and doing a search uncovered the above guideline which Fluent NHibernate seems to violate.
By Praveen Angyan — 8 Aug, 2008 @ 10:17 pm
Constructors are executed bottom-up, so a virtual call could be implemented in a derived class before the constructor for that derived class has been executed. Its a point of caution, not a serious issue.
This is quite nice, but it still more verbose than NHibernate.Mapping.Attributes, or if commerical products are your thing then Diamond Binding (based on NHibernate) uses attributes are even cleaner and comes with a tool which syncs the class definition with your schema.
By Robert — 9 Sep, 2008 @ 1:10 pm
Great project. Keep going.
By Petar Petrov — 12 Dec, 2008 @ 5:12 pm
Is there a way to use the AutoPersistenceModel and set a convention for the table name similar to the way you can with primary keys etc?
var persistenceModel = AutoPersistenceModel.MapEntitiesFromAssemblyOf()
.WithConvention(c => c.GetPrimaryKeyName = p => p.Name + “ID”)
But like
.WithConvention(c => c.GetTableName = t => “tbl” + t.Name)
By Chris Marisic — 12 Dec, 2008 @ 1:01 am
Also is there a way to setup the AutoPerisistanceModel to use component objects like you can with regular mapping
Map(x => x.HireDate);
Map(x => x.Phone,”HomePhone”).WithLengthOf(24);
Component(employee => employee.Address,
address =>
{
address.Map(a => a.City).WithLengthOf(15);
address.Map(a => a.CountryRegionName).WithLengthOf(15);
address.Map(a => a.PostalCode).WithLengthOf(10);
address.Map(a => a.StateProvinceName).WithLengthOf(15);
address.Map(a => a.AddressLine1,”Address”).WithLengthOf(60);
}
);
By Chris Marisic — 12 Dec, 2008 @ 1:05 am
@Chris Please use the Fluent NHibernate google group to ask those kind of questions, you’ll get a much prompter response.
http://groups.google.com/group/fluent-nhibernate
By James Gregory — 12 Dec, 2008 @ 8:40 am
James thanks for pointing the group out to me I missed the link to it on the google code page to it.
By Chris Marisic — 12 Dec, 2008 @ 2:31 pm
Does this approach require that the class being mapped extend from ClassMap ?
If this is the case, the one chance you have at inheritance is lost by extending from ClassMap.
Typically, I see people writing entities that tend to extend from some base entity.
Still looks awesome though!
-K
By Kishore — 5 May, 2009 @ 8:24 pm
Fluent NHibernate doesn’t require your entities to inherit from anything, it’s only the actual mappings themselves that should inherit from ClassMap.
By James Gregory — 5 May, 2009 @ 9:51 pm
Post a comment...