This is the second part in my series of "Thoughts on NHibernate performance". I recommend that you read the first post (insert link) because I will reuse things from that post. In this post I am going to talk about using a stateless session for inserting records to the database by using NHibernate. This is something I didn't talked about in the previous post simply because otherwise the post would become too long. You can find the updated version of the code on my Github account. I won't go in detail about the code only for the new parts.

Stateless session

When you start a new NHibernate session it will automatically track the entities that are retrieved from database. For instance take a look at the following code:

What do you think will happen ? Take a brief moment, no need to rush. When this code is executed the code will result into an update to the database. Why is this ? Because from the moment we fetch the entity, NHibernate starts tracking the changes. So when we change the value of a property on the entity, NHibernate will mark the entity as dirty. When the transaction is committed NHibernate will know which entities, or properties, needs to be updated. This is called a statefull session or session. Throughout this post I will use the term statefull session.

Now you have to know that all this tracking is done in memory and the question is "will performance be better when we use a stateless session". I took the tests, from my previous post, and run them against a stateless session to see the results. Note: this numbers are just an indication. The tests are performed on my local machine.

Before we go to the tests I will show you the code. I created a new class which contains the specific methods for the inserting objects with stateless session.

In the above method a stateless session is created. This has some implications because a stateless session has other methods. For instance when saving the object you don't use the method Save() but you use Insert() instead. The methods Update() and Delete() don't exist on a stateless session object. Actually a stateless session is much closer to ADO.NET than a statefull session.

Now let's take a look at the tests.

Test: 200 records

For the first test I inserted 200 records into the database. I have used the same 3 methods of my previous blogpost. Here are the results for the statefull session:

This are the results when using a stateless session:

When comparing the results you will only see a small improvement. For the first method there is 3ms gain and 2 other only 1ms. Looking at these results you would say that going stateless is not really an improvement. For this reason I created 2 extra tests with much more records.

Test: 2.000 records

In this next test I will insert 2.000 records. Let's take a look at the results

Results for the statefull session (2.000 records):

Results for the stateless session (2.000 records):

You will notice that the difference is much bigger then when inserting 200 records. The first method has a difference of 57ms. The other 2 methods are only 27ms (for HiLo) and 51ms (for Guid). The GUID results are pretty high for this test run.

Test: 10.000 records

In this final test I will insert 10.000 records.

Results for the statefull session (10.000 records):

Results for the stateless session (10.000 records):

When we compare the test results the differences are even bigger then with the previous test. For the first method you will see a difference of 336ms. It' safe to say that when inserting large volumes of data you should consider using a stateless session.


Below you will see a table with all the query results. Note: this numbers are just an indication. The tests are performed on my local machine.

DB generated HiLo generated GUID generated
200 records 95ms 98ms 17ms 16ms 17ms 15ms
2.000 records 905ms 848ms 157ms 130ms 194ms 143ms
10.000 records 4574ms 4238ms 767ms 639ms 839ms 707ms

Something that you will notice is that using a stateless session becomes faster when inserting a large number of records. In the test with 200 records you can see that the differences are actually very small. It's max 3 milliseconds but when we take a look a the test with 2.000 and 10.000 records the difference become greater and greater. Meaning performance is better when inserting a large number of objects. As I said at the summary of my previous post NHibernate is not the best tool to use when doing ETL operations so when inserting 1000 of records take a look at the tools as SqlBulkCopy.

I hope you'll find this post useful.