The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Archive for the 'NHibernate' Category

Using NHibernate In Your Service Layer

Posted by Davy Brion on 11th December 2009

I have an old post where i discuss how you can manage your NHibernate sessions in a service layer scenario.  Now, the example of the service layer code in that post was pretty poor and people were asking for a better example.  Hopefully, this post will do a better job at making sure everything is clear :)

First of all, the idea is to make sure that managing the NHibernate session (creating it, starting a transaction, committing or rolling back the transaction and closing the session) is taken care of automatically so you no longer have to worry about it.  I also want to avoid passing the NHibernate session around all the time.  This means that it will be created automatically when a request is sent to your service layer and stored in some place that will keep the instance alive during the handling of the service layer request.  Every class that needs a reference to the current session (ideally only classes that deal purely with data access) will be able to retrieve it very easily, all in a thread-safe manner that can never be influenced by other concurrent requests.

First of all, you need something to wrap NHibernate’s ISessionFactory.  I use the ISessionProvider for that:

    public interface ISessionProvider

    {

        ISession Create();

    }

 

    public class SessionProvider : ISessionProvider

    {

        private readonly ISessionFactory sessionFactory;

 

        public SessionProvider(string mappingAssemblyName)

        {

            Configuration configuration = new Configuration()

                .Configure()

                .AddAssembly(mappingAssemblyName);

 

            sessionFactory = configuration.BuildSessionFactory();

        }

 

        public ISession Create()

        {

            return sessionFactory.OpenSession();

        }

    }

 

In my case, i configure the IOC container to pass the name of the assembly that contains the mappings to the constructor of the SessionProvider class.  If you’re using this code directly in your application, you could just as well hardcode the name of the assembly here.

You’ll also need something that allows you to store and retrieve the NHibernate session for the duration of the current request.  I use the IActiveSessionManager for that:

    public interface IActiveSessionManager

    {

        ISession GetActiveSession();

        void SetActiveSession(ISession session);

        void ClearActiveSession();

        bool HasActiveSession { get; }

    }

 

    public class ActiveSessionManager : IActiveSessionManager

    {

        private const string sessionKey = "_currentSession";

        private readonly IRequestState requestState;

 

        public ActiveSessionManager(IRequestState requestState)

        {

            this.requestState = requestState;

        }

 

        public ISession GetActiveSession()

        {

            if (Current == null)

            {

                throw new InvalidOperationException("There is no active ISession instance for this thread");

            }

 

            return Current;

        }

 

        public void SetActiveSession(ISession session)

        {

            if (Current != null)

            {

                throw new InvalidOperationException("There is already an active ISession instance for this thread");

            }

 

            Current = session;

        }

 

        public void ClearActiveSession()

        {

            Current = null;

        }

 

        public bool HasActiveSession

        {

            get { return Current != null; }

        }

 

        protected virtual ISession Current

        {

            get

            {

                return requestState.Get<ISession>(sessionKey);

            }

            set

            {

                requestState.Store(sessionKey, value);

            }

        }

    }

 

This class will store the ISession instance in the current request state (definitely click on that link if you don’t know IRequestState yet).

Now we can create our own Unit Of Work.  This is not a pure Unit Of Work because it doesn’t do any change tracking or anything like that, but it does take care of creating an NHibernate session (which does do change tracking and anything that a real Unit Of Work should do) and cleaning it up when the Unit Of Work is completed.  Here’s my implementation:

    public interface IUnitOfWork : IDisposable

    {

        void Clear();

        void Flush();

        ITransaction CreateTransaction();

        ITransaction CreateTransaction(IsolationLevel isolationLevel);

    }

 

    public class UnitOfWork : Disposable, IUnitOfWork

    {

        private readonly IActiveSessionManager sessionManager;

        private readonly ISession session;

        private readonly bool isRootUnitOfWork;

 

        public UnitOfWork(ISessionProvider sessionProvider, IActiveSessionManager sessionManager)

        {

            this.sessionManager = sessionManager;

 

            if (sessionManager.HasActiveSession)

            {

                isRootUnitOfWork = false;

                session = sessionManager.GetActiveSession();

            }

            else

            {

                isRootUnitOfWork = true;

                session = sessionProvider.Create();

                sessionManager.SetActiveSession(session);

            }

        }

 

        public void Clear()

        {

            session.Clear();

        }

 

        public void Flush()

        {

            session.Flush();

        }

 

        public ITransaction CreateTransaction()

        {

            return CreateTransaction(IsolationLevel.ReadCommitted);

        }

 

        public ITransaction CreateTransaction(IsolationLevel isolationLevel)

        {

            if (session.Transaction != null && session.Transaction.IsActive)

            {

                throw new InvalidOperationException("nested transactions are not supported!");

            }

 

            return session.BeginTransaction(isolationLevel);

        }

 

        protected override void DisposeManagedResources()

        {

            if (isRootUnitOfWork)

            {

                if (session != null)

                {

                    session.Close();

                    session.Dispose();

                }

 

                sessionManager.ClearActiveSession();

            }

        }

    }

 

The idea is very simple.  When the Unit Of Work is created, it asks the IActiveSessionManager if there is already an active session available.  If not, it will create a new session through the ISessionProvider, and store it as the active session through the IActiveSessionManager.  In the old implementation, the Unit Of Work would automatically create a new session in the constructor, but this obviously causes problems if you want to reuse a certain request handler from another request handler if they both depend on a IUnitOfWork instance.   The IUnitOfWork interface doesn’t expose a lot of functionality but it’s all you need to manage your session in your service layer.  It gives you the ability to create a transaction, clear the session and flush the session.  When the IUnitOfWork is disposed, it will clean up the session and instruct the IActiveSessionManager to get rid of the session for this request. 

Once you have this, you have all you need to prepare your service layer to take care of NHibernate session management automatically.  I’m going to base the following service layer code example on Agatha (just because i think it’s the easiest way to implement a service layer ;) ) but you can do exactly the same in your service layer.  The important part is that you should configure your IOC container to inject a new instance of IUnitOfWork into the class that handles your service request.  When the container injects the new instance, the NHibernate session will be created and stored in the IActiveSessionManager so there’s no more reason why you would have to do this yourself.

Now, i use the following class as the base class for all my request handlers that need NHibernate support:

    public abstract class NhRequestHandler<TRequest, TResponse> : RequestHandler<TRequest, TResponse>

        where TRequest : Request

        where TResponse : Response

    {

        public IUnitOfWork UnitOfWork { get; set; }

 

        protected override void DisposeManagedResources()

        {

            if (UnitOfWork != null) UnitOfWork.Dispose();

        }

 

        public override Response Handle(Request request)

        {

            using (ITransaction transaction = UnitOfWork.CreateTransaction())

            {

                Response response;

 

                try

                {

                    response = base.Handle(request);

                    transaction.Commit();

                }

                catch (Exception handlerException)

                {

                    transaction.Rollback();

                    throw;

                }

 

                return response;

            }

        }

    }

 

(Note: the real implementation contains a bit more logging but other than that this is the real thing)

If you don’t understand the whole request handling concept, please check out the first 3 posts in this series.  Regardless of whether you’re using Agatha, your own Request/Response Service Layer or a classic (dare i say old-school?) service layer, the idea should be the same.  Make sure this code is centralized in one place so you don’t have to repeat yourself all over your service layer code.   Btw, in this case the IUnitOfWork instance is injected by the IOC container through Setter Injection instead of Constructor Injection.  I’ve already discussed the reasons on why i prefer Setter Injection in this case here.

Now, you’re going to have some classes that will need to use an ISession instance to perform their tasks.  I always create Repository classes for that, but the following approach would be similar for any other type of class which needs an ISession.   Call them Data Access Objects, Data Access Classes or Sloppy Joes for all i care.   Whatever you call these classes, they need a dependency on the IActiveSessionManager.   Simply declare the IActiveSessionManager to be a dependency of your Sloppy Joe, i mean, Repository or DAO or whatever, like this:

    public class Repository<T> : IRepository<T>

    {

        private readonly IActiveSessionManager activeSessionManager;

 

        public Repository(IActiveSessionManager activeSessionManager)

        {

            this.activeSessionManager = activeSessionManager;

        }

 

        protected ISession Session

        {

            get { return activeSessionManager.GetActiveSession(); }

        }

 

Now you can write request handlers like this:

    public class GetCustomersRequestHandler : NhRequestHandler<GetCustomersRequest, GetCustomersResponse>

    {

        private readonly IRepository<Customer> repository;

 

        public GetCustomersRequestHandler(IRepository<Customer> repository)

        {

            this.repository = repository;

        }

 

        public override Response Handle(GetCustomersRequest request)

        {

            var response = CreateTypedResponse();

            response.Customers = ConvertToDtos(repository.FindAll(request.Criteria));

            return response;

        }

 

        private CustomerDto[] ConvertToDtos(IEnumerable<Customer> customers)

        {

            // …

        }

    }

 

Obviously, this is a simple example but it works just as well for complex request handlers.  Your NHibernate session is created and cleaned up automatically, without you having to write that code every single time. Each request handler will run in a transaction, and it will be committed or rolled back automatically without you having to do anything for it.  And you only need to access the ISession instance in your Sloppy Joes.

Also keep in mind that you can also use the the ISessionProvider, IActiveSessionManager and IUnitOfWork in a purely web-based scenario as well if you want to.

Posted in NHibernate | 15 Comments »

Testing CRUD Operations With NHibernate

Posted by Davy Brion on 7th December 2009

I was asked to show how you can easily do CRUD tests, so here’s a base class that makes it very easy

    public abstract class CrudTest<TEntity, TId> : NHibernateTest

        where TEntity : IHaveAnId<TId>

    {

        [Test]

        public virtual void SelectQueryWorks()

        {

            session.CreateCriteria(typeof(TEntity)).SetMaxResults(5).List();

        }

 

        [Test]

        public virtual void AddEntity_EntityWasAdded()

        {

            var entity = BuildEntity();

 

            InsertEntity(entity);

 

            session.Evict(entity);

 

            var reloadedEntity = session.Get<TEntity>(entity.Id);

 

            Assert.IsNotNull(reloadedEntity);

            AssertAreEqual(entity, reloadedEntity);

            AssertValidId(reloadedEntity);

        }

 

        [Test]

        public virtual void UpdateEntity_EntityWasUpdated()

        {

            var entity = BuildEntity();

 

            InsertEntity(entity);

            ModifyEntity(entity);

            UpdateEntity(entity);

 

            session.Evict(entity);

 

            var reloadedEntity = session.Get<TEntity>(entity.Id);

            Assert.IsNotNull(reloadedEntity);

            AssertAreEqual(entity, reloadedEntity);

        }

 

        [Test]

        public virtual void DeleteEntity_EntityWasDeleted()

        {

            var entity = BuildEntity();

 

            InsertEntity(entity);

            DeleteEntity(entity);

 

            Assert.IsNull(session.Get<TEntity>(entity.Id));

        }

 

        protected virtual void InsertEntity(TEntity entity)

        {

            session.Save(entity);

            session.Flush();

        }

 

        protected virtual void UpdateEntity(TEntity entity)

        {

            session.Update(entity);

            session.Flush();

        }

 

        protected virtual void DeleteEntity(TEntity entity)

        {

            session.Delete(entity);

            session.Flush();

        }

 

        protected abstract TEntity BuildEntity();

        protected abstract void ModifyEntity(TEntity entity);

        protected abstract void AssertAreEqual(TEntity expectedEntity, TEntity actualEntity);

        protected abstract void AssertValidId(TEntity entity);

    }

 

Simply inherit from this class, implement the BuildEntity, ModifyEntity, AssertAreEqual and AssertValidId methods and that’s it.  Those methods are usually pretty simple.  In BuildEntity you just create an unpersisted entity and assign values to the properties, in ModifyEntity you modify the properties, and in AssertAreEqual you compare the properties of both instances.  In AssertValidId, you make sure that the ID value is ok (depending on your identifier strategy).

This is good for regular CRUD operations, though we typically add extra tests when we want to test cascades or one-to-many associations mapped with inverse=”true”.

Posted in NHibernate, Test Driven Development | 4 Comments »

Unit Testing An NHibernate Application

Posted by Davy Brion on 6th December 2009

Grant Palin recently asked me for an in-depth article on TDD’ing an NHibernate application. While this post won’t be very in-depth, it might be helpful already.  There are basically two approaches that i’ve seen used with good results, though there are obviously more approaches that you can use.  I’m going to limit the scope of this post to the following two approaches though, and i’ll also discuss exactly what we test.

Creating a new database for each test (or testfixture)

This approach creates the database at the beginning of each test (or testfixture), runs the test (or tests in the fixture), and then destroys the database after the test (or testfixture) completed.  The easiest way to do this is to create a base test class that all of you data access test class should inherit from.  Here’s a simple example:

    public class NHibernateTest

    {

        private Configuration configuration;

        protected ISessionFactory sessionFactory;

 

        [TestFixtureSetUp]

        public void TestFixtureSetup()

        {

            configuration = new Configuration()

                .Configure()

                .AddAssembly("YourAssemblyName");

 

            new SchemaExport(configuration).Create(false, true);

            sessionFactory = configuration.BuildSessionFactory();

        }

 

        [TestFixtureTearDown]

        public void TestFixtureTearDown()

        {

            new SchemaExport(configuration).Drop(false, true);

        }

 

        protected ISession CreateTransactionalSession()

        {

            var session = sessionFactory.OpenSession();

            session.BeginTransaction();

            return session;

        }

    }

 

This class will create the database from scratch once for each TestFixture, which means that each test in the fixture will use the same database.  It also destroys the database at the end of the fixture.  It creates the database based on your mappings, and as you can see, you really don’t have to do a lot for this.  If you want the database to be recreated and dropped for each test, then you obviously need to move the code in the TestFixtureSetup and TestFixtureTearDown methods to your regular SetUp and TearDown methods.  If you go that route, i’d advise you to include empty template methods before and after the setup and teardown so you can plug in some extra code before and after these operations in your derived test classes.

The biggest benefit of this approach is that you don’t have any possibly present state in the database that can influence your tests.  The downside is that you can’t rely on certain data (eg reference data) to be present and you have to recreate it whenever you need it.   You can also use multiple transactions in your tests, though you are also responsible for cleaning any data that is left in the database at the end of each test.  You also need to guarantee that this always happens because any data that is left by one test might influence another one.   Also, if you leave data in the database, that might lead to problems when dropping the database, so you really need to be careful with this.

Another problem with this example is that there is no automatic way to push the ISession instance to your data access components.  That could easily be added though, depending on how your data access components retrieve a reference to a valid ISession.

Tests that automatically roll back their transactions

This is the approach that we always use at work.  These tests require your database to be set up in a valid manner before your tests begin.  Each test uses one transaction, which is automatically rolled back at the end of the test to prevent the possibility of any test data remaining in the database.   With this way of testing, it’s also possible to provide some kind of ‘known state’ in the database (eg reference data) that you can use from within your code.

Here’s the NHibernateTest class that our NHibernate test classes all inherit from:

    public abstract class NHibernateTest

    {

        protected static readonly ActiveSessionManager activeSessionManager = new ActiveSessionManager();

 

        private UnitOfWork unitOfWork;

        protected ISession session;

 

        protected abstract ISessionProvider GetSessionProvider();

 

        protected virtual IActiveSessionManager GetActiveSessionManager()

        {

            return activeSessionManager;

        }

 

        [SetUp]

        public void SetUp()

        {

            BeforeSetup();

            var sessionManager = GetActiveSessionManager();

            unitOfWork = new UnitOfWork(GetSessionProvider(), sessionManager);

            session = sessionManager.GetActiveSession();

            unitOfWork.CreateTransaction();

            AfterSetup();

        }

 

        [TearDown]

        public void TearDown()

        {

            BeforeTearDown();

 

            if (unitOfWork != null)

            {

                unitOfWork.Dispose();

            }

 

            unitOfWork = null;

            AfterTearDown();

        }

 

        protected virtual void BeforeSetup() { }

        protected virtual void AfterSetup() { }

        protected virtual void BeforeTearDown() { }

        protected virtual void AfterTearDown() { }

    }

 

Now, this example uses our UnitOfWork and ActiveSessionManager classes (read this if you haven’t seen those yet) to make sure that our data access components can access the current ISession instance.  Each test has a valid ISession present, which has already created a transaction and we can create/modify/delete data, run our queries, modify some stuff again, run our queries again and perform our assertions, all in the same transaction.  After the test is completed, the transaction is never committed (and thus, automatically rolled back) so none of that data ever remains in the database.

What Exactly Do We Test?

Well, we test everything basically.  We test all of our CRUD operations (again, with a simple base class which only requires you to implement the BuildEntity, ModifyEntity and AssertEqual methods and does all of the operations and checks automatically) for each entity.  That’s right, for each entity.  The extra work that this requires really doesn’t take a lot of time and it lets us know for a fact that our mappings are valid.

We also test every custom query that we write, always using the following approach: create some test data, flush the session, perform your query and verify that the expected data has indeed been returned by the query, and also that data that shouldn’t have been returned isn’t there.

And that’s pretty much it.  We mock the data layer in all of our other tests, so our CRUD and query tests are the only ones that actually use NHibernate and the database.  But CRUD actions and queries are tested very extensively.

Posted in NHibernate, Test Driven Development | 11 Comments »

Why NHibernate Entities Need A Public Or Protected Parameterless Constructor

Posted by Davy Brion on 4th October 2009

I have an older post where i discuss how you can implement a Value Object with NHibernate. In that post i mentioned the following:

NHibernate allows a private default constructor for Value Objects, but for Entities you will need a default public or protected constructor as private is not sufficient.

I got the following comment from someone:

I too am trying to determine how well NHibernate lives up to the promise of persistence ignorance. I can definitely live with unnecessary private constructors, but I’m dubious about adding protected constructors just to support an ORM.

At any rate, I was surprised by the sentence I quoted, because I didn’t realize there were any circumstances in which NHibernate required protected default constructors.

Once again, the answer is related to the dynamic proxies that NHibernate uses. Value Objects will never be proxied by NHibernate, so NHibernate only needs a private default constructor to create the instances. If an entity is eligible for lazy loading however, then NHibernate will create a type which inherits from your entity (this is described in depth here and here). Which means that we really need either a public or protected constructor in entity classes that are eligible for lazy loading. Consider the following class:

    public class SomeEntity

    {

        public SomeEntity(string someRequiredValue)

        {

        }

 

        private SomeEntity()

        {

        }

    }

If we try to create the following derived class:

    public class SomeEntityProxy : SomeEntity

    {

    }

We get the following compiler error:

Error 1 ‘ConsoleApplication1.SomeEntity.SomeEntity()’ is inaccessible due to its protection level

It’s a silly example, but it does show why entity types need at least a public or a protected default constructor and why a private one isn’t sufficient.

Posted in NHibernate | 4 Comments »

Must Everything Be Virtual With NHibernate, Part III

Posted by Davy Brion on 27th September 2009

In the previous post i showed a piece of code which suffers from 2 problems and asked you guys to spot both problems. One of the problems was pointed out in the comments, but nobody mentioned the other one.

Once again, this is the code example:

transitive_persistence41

Instead of making everything virtual, only properties that are eligible for lazy-loading have been made virtual. Now, the line of code that is problematic is obviously the one where the DiscountPercentage of the customer backing field is accessed. I will address using the field instead of the property later on in this post so bear with me for now.

There are 2 situations in which this code will fail badly. The first situation is when you’re dealing with a proxy of an Order. If you have an uninitialized proxy of Order, and you call the non-virtual CreateOrderLine method then you will get a NullReferenceException because the proxy can’t intercept the call to CreateOrderLine, and because it also can’t intercept accessing the customer field, which will be null at that time. This problem was correctly spotted by one of the people who left a comment.

The other problem is far worse, IMO. Suppose you have a genuine instance of an Order object, but its reference properties haven’t been loaded yet and are uninitialized proxies. If there is no requirement for every public member of a proxy-able type to be virtual, then we can pretty much assume that the DiscountPercentage of the Customer class is also non-virtual. Which means that with this code, we have no possible way of intercepting the call to the Customer’s proxy’s DiscountPercentage property. Unfortunately, DiscountPercentage will have its default value of 0, so you won’t get an exception… instead, the customer gets no discount even though its record in the database might have a discount set.

The possibility of running into one of these problems due to usage of an ORM and depending on how an object is loaded is simply unacceptable. Some people commented on the usage of the customer backing field instead of the Customer property with a “then simply don’t do that” response. That’s not an acceptable solution to this problem, it’s a lame workaround at best. There are plenty of reasons why people would use the backing field in their code instead of the property and if they run into this problem, they definitely will blame the ORM. And rightfully so, i might add.

Posted in NHibernate | 12 Comments »

Must Everything Be Virtual With NHibernate, Part II

Posted by Davy Brion on 23rd September 2009

I already tried to explain this before, but here’s a simple example from a presentation i recently did on NHibernate:

transitive_persistence4

As you can see, only the properties of associations that are eligible for lazy-loading are virtual in this piece of code, because that is what many people seem to want. There are actually 2 different ways in which this can cause problems… can you spot both problems?

Posted in NHibernate | 10 Comments »

Slides Of My NHibernate Talk

Posted by Davy Brion on 10th September 2009

I’m giving a talk on NHibernate for the Belgian Visual Studio User Group right now (gotta love scheduled posts!). You can download the slides of the presentation here. I don’t like most typical technical presentations, so i wanted a slightly different approach. So this presentation probably isn’t like most presentations that you may be used to. This is also the first time i’m giving a ‘big’ talk for a group of people that i don’t know personally, so hopefully, it’ll be alright and i won’t screw up ;) .

If i did screw up: sorry, but at least it was free :p

Posted in NHibernate | 15 Comments »

Of Course NHibernate Is Slow When You Use It Incorrectly

Posted by Davy Brion on 19th August 2009

Just saw the following post where the performance of NHibernate and Entity Framework is compared for a couple of different operations. Spoiler alert: NHibernate loses. As it typically does in these kinds of ‘benchmarks’ or ‘comparisons’ that seem to pop up frequently lately.

For some reason, a lot of people seem to think that opening an NHibernate session and performing thousands of operations is a valid use case. It’s not. Far from it actually. And with all of the features that NHibernate offers, it can’t possibly perform well in such a scenario. See, an NHibernate session is a unit of work. A unit of work is a business transaction which is typically short and small, but it should never be something huge. Your DBA probably won’t appreciate huge database transactions on the database either.

Whenever you load an object through NHibernate, it will be tracked by the session that loaded it. That means that the NHibernate session keeps a reference to it, and performs a series of checks on it periodically, depending on what you’re doing and some configuration settings such as the FlushMode. For instance, suppose you’ve loaded a hundred different entities in one session. If the FlushMode is set to automatic, it means that NHibernate will perform a dirty check for each entity associated with the session before each query is executed. The more entity instances you’ve loaded, the longer this takes (obviously). If you take this to an extreme level, like loading thousands of entities like most of these ‘benchmarks’ do, performance will naturally be horrible.

Each entity instance is also stored in the first level (or session level) cache. That means that whenever you retrieve a row from the database, NHibernate will check if an instance of that row already exists in the first level cache. Again, the more instances you’ve loaded, the larger the overhead of this will be. There are also a lot of possible extension points where you can plug in custom logic. Again, there is a very minor cost that comes with this extensibility and as you can expect, that minor cost can add up to something much more noticable once you start dealing with an unreasonably large number of instances in your session.

Always keep in mind that an ORM (and this goes for every ORM) is most suitable for OLTP. Using an ORM for batch processing jobs or large data processing operations in general is simply put a bad idea. And they will never perform as well as other solutions in these scenarios. So please don’t bother even benchmarking ORM performance in non OLTP usage because it quite simply doesn’t make sense to do so, and the results will be completely untrustworthy anyway.

An ORM can offer you nice performance gains in OLTP scenarios simply by trying to minimize database connectivity, minimizing the number of database operations, and relatively sane caching usage. Unfortunately, these are aspects that are never tested in these ‘benchmarks’ or ‘comparisons’.

Posted in NHibernate, Performance | 14 Comments »

One Of My Favorite NHibernate 2.1 Features

Posted by Davy Brion on 30th July 2009

Check out the following piece of code:


            Session.CreateQuery(
                @"delete from DocumentTypeAssignment
                  where Id.DmsDocument in (from DmsDocument where Id = :documentId) and
                        Id.DocumentType.Id not in (:newDocumentTypeIds)")
                .SetInt64("documentId", dmsDocumentId)
                .SetParameterList("newDocumentTypeIds", newDocumentTypesToAssign.ToList(), NHibernateUtil.Int64)
                .ExecuteUpdate();

(pay no attention to Id.DmsDocument or Id.DocumentType… it’s a composite key for a legacy table)

Which results in this SQL statement:


delete
    from
        DocumentManagement.DocumentTypeAssignment
    where
        (
            DmsDocumentID in (
                select
                    dmsdocumen1_.ID
                from
                    DocumentManagement.DmsDocument dmsdocumen1_
                where
                    dmsdocumen1_.ID=@p0
            )
        )
        and (
            DocumentTypeID not in  (
                @p1 , @p2
            )
        );
    @p0 = 1634, @p1 = 2313, @p2 = 2310

Posted in NHibernate | 4 Comments »

Avoid Using NHibernate With NUnit 2.4.6

Posted by Davy Brion on 24th June 2009

We just spent about 2 hours trying to find out why our NHibernate tests were about 10x slower on our build server than they were on our local machines. I had noticed lately that the build for one of our projects was taking longer and longer but i hadn’t really timed the difference. This project has about 1200 tests that use NHibernate and they run in about 45-60 seconds on my local machine. It turns out they took around 15 minutes on the buildserver when running them through TeamCity.

I logged into the buildserver and ran the tests manually using nunit’s console runner (with an NUnit-2.4.7 build that i happened to have installed somewhere on the machine) and they only took about 45 seconds. After a lot of guesswork and screwing around, it turned out that we never modified our base build script (why yes, i do believe in build script inheritance) to use a newer version of NUnit. We set up the buildserver about 1 year ago, and at that time, the latest stable NUnit version that TeamCity supported was NUnit 2.4.6. Our base build script was still referring to NUnit 2.4.6, which apparently sets log4net to use debug level logging. Now, NHibernate logs a huge amount of information at the debug level, so this turned out to slow down all of our builds that had NHibernate tests.

We changed the the 2.4.6 version in our script to 2.4.7 and the build time of this particular project decreased from around 50 minutes to about 35 minutes. Yes, that’s still a lot but this is a huge project with a lot of legacy tests and the entire build process is pretty complex. Other projects went from build times from around 7 minutes to about 2 minutes.

That’s a pretty nice improvement for simply changing a “6″ to a “7″ ;)

Posted in NHibernate, Performance, Test Driven Development | 3 Comments »