Tigraine

Daniel Hoelbling-Inzko talks about programming

Comparing Castle ActiveRecord to Fluent NHibernate

Posted by Daniel Hölbling on May 27, 2009

I’ve used my fair share of ORM tools lately and I keep coming back to NHibernate more and more. But sometimes it feels like “too much”. Going for a dedicated data access layer often feels like a bit of overkill and isn’t all that exciting to do, so for smaller projects I sometimes took the easy way and used LinQ to Sql.
Usually LinQ to Sql would then come around to bite me at some point and I’d hate myself for using it. So when I lately tried Castle ActiveRecord (watch this wonderful presentation by Ayende and Hammet at InfoQ: Painless Persistence with Castle ActiveRecord) I was blown away: A simpler way to build stuff with NHibernate.
No complete abstraction of NHibernate, but a layer ontop that makes life easier. (You can access the Session manually and do your crazy NHibernate stuff if you want to).

Since ActiveRecord was created to avoid some of the crazy configuration stuff that was in NHibernate at that time, I thought it might be interesting to compare ActiveRecord to the current state of NHibernate configuration, namely: Fluent NHibernate.

This is by no means a matchup, what you use hugely depends on your needs. And since both are essentially the same it boils down to taste. I haven’t used either for any real application (only old NHibernate with XML), so this is my personal rundown on the samples and spikes I did lately.

Let’s assume the typical Blog sample model:

model

I’ll only focus on the BlogPost class since it is on both ends of a parent/child relationship.

Mapping

First, how does the the ActiveRecord mapping look like:

[ActiveRecord]
public class BlogPost : ActiveRecordBase<BlogPost>
{
    [PrimaryKey]
    public int Id { get; set; }
    [Property]
    public string Headline { get; set; }
    [Property]
    public string PostText { get; set; }
    [Property]
    public DateTime PostedOn { get; set; }
    [BelongsTo]
    public User Poster { get; set; }
    [HasMany]
    public IList<Comment> Comments { get; set; }
}

Now the NHibernate mappings:

public class BlogPost
{
    public virtual int Id { get; set; }
    public virtual string Headline { get; set; }
    public virtual User Poster { get; set; }
    public virtual IList<Comment> Comments { get; set; }
    public virtual string PostText { get; set; }
    public virtual DateTime PostedOn { get; set; }
}
public class BlogPostMap : ClassMap<BlogPost>
{
    public BlogPostMap()
    {
        Id(m => m.Id);
        Map(m => m.Headline);
        Map(m => m.PostText);
        Map(m => m.PostedOn);
        HasMany(m => m.Comments);
        References(m => m.Poster);
    }
}

Cool, both APIs look good. Very readable and no XML.

NHibernate has the ability to have the Model separated from the mappings, a feature that I like when doing enterprise applications. But for something simpler, not really relevant. Where Fluent NHibernate really blows AR away is the auto mapper feature Ayende is so happy with.

Initialization

ActiveRecord hasn’t departed from XML yet, but there are three ways to load a configuration. The simplest would probably be the inplace configuration source, but it’s more or less a in-memory mirror of the XML config:

var properties = new Hashtable();
properties.Add("hibernate.connection.driver_class", "NHibernate.Driver.SQLite20Driver");
properties.Add("hibernate.dialect", "NHibernate.Dialect.SQLiteDialect");
properties.Add("hibernate.connection.provider", "NHibernate.Connection.DriverConnectionProvider");
properties.Add("hibernate.connection.connection_string", "Data Source=:memory:;Version=3;New=True;");
var source = new InPlaceConfigurationSource();
source.Add(typeof (ActiveRecordBase), (IDictionary<string, string>) properties);
ActiveRecordStarter.Initialize(typeof(BlogPost).Assembly, source);
ActiveRecordStarter.CreateSchema();

The Fluent NHibernate configuration looks way better since you don’t have to worry about connectionstrings or other properties that nobody remembers:

public static ISessionFactory CreateSessionFactory()
{
    return
        Fluently
            .Configure()
            .Database(SQLiteConfiguration.Standard.InMemory())
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<BlogPost>())
            .ExposeConfiguration(BuildSchema)
            .BuildSessionFactory();
}

private static void BuildSchema(Configuration config) {     new SchemaExport(config)         .Create(false, true); }

I’d vote for Fluent NHibernate on this one, but having the configuration externalized in XML is something you’d probably do anyway.

Where the differences really begin are the querying:

Querying with ActiveRecord is mostly done through static methods, so ease of use is king here:

var post = BlogPost.Find(1);

While NHibernate requires me to retrieve a ISession before giving me access to anything.

var mySession = factory.OpenSession();
var post = mySession.Get<BlogPost>((object)1);

The one is more OO, the other is simpler. I have to say I prefer the added complexity since it makes it easier to test that your code interacts with the session object. (Although I’d not overuse that, going against an in-memory db and verifying the results should be the better way to create durable tests).

Since both AR and NH use the NH Criteria API I won’t compare complex queries.

So, how to conclude on the usability? Not having to think about how to pass the session around is quite nice, but when using NHibernate you could easily just write your session to some global and use it from there.

Validation

Now, what would a ORM be without a good validation framework.

ActiveRecord comes prepacked with the Castle.Components.Validator assembly that allows a rather cool attribute based validation API:

[Property, ValidateEmail, ValidateNonEmpty]
public string Email { get; set; }

var user = new User();
if (user.IsValid())
    user.Save();

While NHibernate doesn’t have a built-in Validation framework, there is the NHibernate Validator (documentation) project that also allows a very clean attribute based validation.

[NotNull]
public static string blacklistedZipCode;

But as before, it’s a bit “heavier” than AR and allows you to have external ValidatorClasses if you need them. Also cool, but something I don’t really care about is that NHV is also XML based, so you could allow your users/admins to tweak the validation rules after deployment.

I guess that’s enough for now, use what you find suits your project better.  :)

Filed under net, castle, nhibernate
comments powered by Disqus

My Photography business

Projects

dynamic css for .NET

Archives

more