Tigraine

Daniel Hoelbling-Inzko talks about programming

Comparing Castle ActiveRecord to Fluent NHibernate

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

Mapping large text or binary values with NHibernate

I encountered the following error when trying to map a large String to my SQL2005 database:

SQL Error Code -2146232060: “String or binary data would be truncated”

The issue here is that Nhibernate maps all string values by default as nvarchar(255) and so inserting something bigger to a field causes this nasty sql error. My mapping declaration looked like this:

<property name="Comments" />

After some searching I found Ayende’s post on NHibernate and large text fields gotchas that almost solved the issue, except for one thing, I didn’t know where to put the sql-type attribute. Turns out it’s defined in chapter 15 of the NHibernate doc (while mapping files are chapter 5).  
The sql-type=”NTEXT” attribute can only reside on the <column node beneath the <property node. So the correct mapping looks like this:

<property name="Comments" type="StringClob">
  <column name="Comments" sql-type="NTEXT"/>
</property>

If you don’t define the sql-type attribute even the StringClob field will be created as a nvarchar(255) by NHibernate (but it can map to a NText field if the schema exists).

Filed under net, nhibernate

Virtual member call in constructor and NHibernate

As you may have noticed, I’ve been doing some NHibernate work lately and really had a great time with this absolutely amazing ORM. Especially now that Microsoft abandoned Linq to SQL I really feel good about having made the step towards NHibernate.

Yesterday was one of those tricky days when something breaks and you have no clue why.

I have a table called “Orders” and there are “OrderItems”.

image

By writing the tests upfront, I found out that I’d like to be able to just say Repository.Add(Order) instead of persisting the Order and afterwards looping through the OrderItems and persisting them too.

To achieve this I changed the mapping to something like this:

<set name="OrderItems" cascade="all">
  <key column="OrderId" />
  <one-to-many class="OrderItem"/>
</set>

The cascade=all statement is what I searched for initially. When the order gets persisted, all OrderItems in the collection get persisted too, and everything is well.

But, since my POCO object looks like this:

public class Order
{
    public virtual long Id { get; set; }
    public virtual ISet<OrderItem> OrderItems { get; set; }
}

I got NullReferenceException whenever I tried to access OrderItems on new Order objects. And I thought, hey.. kinda sucks newing up the collection in my business layer, why not init it in it’s constructor:

    public Order()
    {
        OrderItems = new HashedSet<OrderItem>();
    }

So I could just do Order.OrderItems.Add(OrderItem) without having to instantiate a HashedSet anywhere.
I got a bit cautious when Visual Studio underlined OrderItems and made the cryptic announcement: “Virtual member call in constructor”.


Totally unaware of what this means, I just went on and ran my tests.

Imagine my face when almost all my tests failed due to an omnious nHibernateException:

NHibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

I didn’t figure this out until today, but it had to do with the “Virtual member call in constructor” warning. I discovered this post by Brad Abrams that explains the topic.

Looks like if you set the collection in the constructor of the POCO object NHibernate will break with the above Exception.
Solution to avoid this? Init the collection from calling-code instead of within the object.

What would have helped the issue would be to not have concrete POCO objects but rather use interfaces instead of virtual members (Read Fabio Maulo’s post entity-name in action: Entity Abstraction on that topic).

Sourcecontrol and Databases, when ORM comes in handy

I encourage every one (even single developers) to use a Sourcecontrol system such as SVN and AnkhSVN to do development. Put all your project files (and external dependencies) under source control and maybe even get a continuous integration server setup.

And still, even if you’ve done all of this, chances are high you still have one external dependency in your project: the Database!

And this is where the pain starts, if you don’t find some way how to put your DB schema under source control too, you’ll end up going back to old versions and having no database of that date.

There are however several ways to solve this that I can think of:

  • Make your CI server fetch a schema script every time a build is triggered.
  • Make creating a schema script part of your build process

And .. guess what? There’s a simpler way :).
If you’re using a ORM tool you should always have your database model somewhere in the mapping files.

Because the mapping files tell the ORM the structure of the DB, they essentially contain all relevant information needed to generate a schema without the need to have SQL scripts.

In NHibernate for example, you can simply do a:

var cfg = new Configuration();
cfg.Configure();
cfg.AddAssembly(typeof (Person).Assembly);

new SchemaExport(cfg).Execute(false, true, false, false);

And the mapper will go out and create all necessary tables and relationships in your database.

By having an ORM capable of recreating the schema, I no longer need to keep the Database itself under source control, because the necessary information to recreate the schema is already in my source tree.

My Photography business

Projects

dynamic css for .NET

Archives

more