Aug 09, 2008 / nhibernate ~ .net
Fluent NHibernate and those sweet LINQ repositories

Fluent NHibernate is a tool that lets you easily write NHibernate mappings.

I downloaded the code and was awe-struck. It's really tidy and full of nicely implemented ideas.

####In-Memory Repository One of them was the in-memory repository class. It uses LINQ for queries, and keeps an in-memory cache of objects. Check out this test-cases that demonstrates it's use.

        InMemoryRepository repository = new InMemoryRepository();

        repository.Save(new Case { Name = "Jeremy", Number = 10 });
        repository.Save(new Case { Name = "Darth Vader", Number = 5 });
        repository.Save(new Case { Name = "Darth Maul", Number = 6 });
        repository.Save(new Case { Name = "Luke", Number = 12 });
        repository.Save(new Case { Name = "Han Solo", Number = 6 });
        repository.Save(new Case { Name = "Eric", Number = 5 });
        repository.Save(new Case { Name = "Corwin", Number = 4 });

        repository.FindBy<Case>(c => c.Name == "Corwin").Name.ShouldEqual("Corwin");
        repository.FindBy<Case>(c => c.Number == 10).Name.ShouldEqual("Jeremy");
        repository.FindBy<Case>(c => c.Number == 6 && c.Name == "Han Solo").Name.ShouldEqual("Han Solo");

Gotta love the Star-Wars geekery :)

This kind of repository is useful for testing domain logic without hitting the DB. This in turns makes domain model testing very fast. For example, the 263 in-memory test take only 4 seconds to complete. I could live with that.

####LINQ for NHIbernate Repository Jeremy has also created a real repository that implements the same interface as the in-memory one. That means it also uses LINQ. And that means it uses LINQ for NHIbernate - hurrah !

Here's the real repository in action:

        ISession session = _source.CreateSession();

        session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 34 });
        session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 35 });
        session.SaveOrUpdate(new Record { Name = "Jessica", Age = 29 });
        session.SaveOrUpdate(new Record { Name = "Natalie", Age = 25 });
        session.SaveOrUpdate(new Record { Name = "Hank", Age = 29 });
        session.SaveOrUpdate(new Record { Name = "Darrell", Age = 34 });
        session.SaveOrUpdate(new Record { Name = "Bill", Age = 34 });
        session.SaveOrUpdate(new Record { Name = "Tim", Age = 35 });
        session.SaveOrUpdate(new Record { Name = "Greg", Age = 36 });

        Repository repository = new Repository(_source.CreateSession());
        Record record = repository.FindBy<Record>(r => r.Age == 34 && r.Name == "Jeremy");
        record.Name.ShouldEqual("Jeremy");
        record.Age.ShouldEqual(34);

There are currently only 9 integration tests that actually use NHIbernate and hit a DB. Pretty cool considering the nature of the project.

####Lots to Learn There's a lot to learn from this project.

One thing is that not hitting a database for 90% of your tests is a GREAT THING.

In this project, the 9 tests that hit the database take a whopping 7 seconds to run on my machine! That's 0.8 seconds per test on average. The in-memory tests take only 0.015 seconds each on average.

####Favourite Mapping Technique? I have a feeling that Fluent-NHibernate will become my favourite way of writing mappings for NHIbernate. And, I soon hope that it will soon be my favourite way of NOT writing mappings for NHibernate :) Of course, they'll need to get their Auto Mapping working for that, but I believe they'll do it within the next 2-3 months.

I now looking forward to browsing more of the code and trying out the tool...


You may also like...