nHibernate Archives - Anuj Varma, Hands-On Technology Architect, Clean Air Activist https://www.anujvarma.com/category/technology/n-tier-apps/nhibernate/ Production Grade Technical Solutions | Data Encryption and Public Cloud Expert Wed, 12 Mar 2014 22:54:23 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://www.anujvarma.com/wp-content/uploads/anujtech.png nHibernate Archives - Anuj Varma, Hands-On Technology Architect, Clean Air Activist https://www.anujvarma.com/category/technology/n-tier-apps/nhibernate/ 32 32 Hibernating Rhinos – nHibernate Profiler https://www.anujvarma.com/hibernating-rhinos-nhibernate-profiler/ https://www.anujvarma.com/hibernating-rhinos-nhibernate-profiler/#respond Wed, 12 Mar 2014 22:54:23 +0000 http://www.anujvarma.com/?p=2310 1. To get started with this powerful profiler, simply install the NuGet package (look for nHibernate Profiler).       2.Installing it places all the required assemblies in your project […]

The post Hibernating Rhinos – nHibernate Profiler appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
1. To get started with this powerful profiler, simply install the NuGet package (look for nHibernate Profiler).

 

nHibernate_profiler_nuget 

 

2.Installing it places all the required assemblies in your project AND provides you with a Bootstrapper class to launch the profiler.

   1: public static class NHibernateProfilerBootstrapper

   2:     {

   3:         public static void PreStart()

   4:         {

   5:             // Initialize the profiler

   6:             NHibernateProfiler.Initialize();

   7:             

   8:             // You can also use the profiler in an offline manner.

   9:             // This will generate a file with a snapshot of all the NHibernate activity in the application,

  10:             // which you can use for later analysis by loading the file into the profiler.

  11:             // var filename = @"c:\profiler-log";

  12:             // NHibernateProfiler.InitializeOfflineProfiling(filename);

  13:         }

  14:     }

3. The only caveat I ran into was that even though the Bootstrapper initialization fired correctly (and launched the UI for the profiler), it did not capture any nHibernate traffic. To work around this, one can place the initialization code in Global.asax – to ensure it gets fired.

Global.asax.cs

   1: protected void Application_Start(object sender, EventArgs e)

   2:         {            

   3:             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();

   4:         }

Once I had this code in place, the profiler launched correctly AND captured traffic the way it was intended to.

The post Hibernating Rhinos – nHibernate Profiler appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
https://www.anujvarma.com/hibernating-rhinos-nhibernate-profiler/feed/ 0
nHibernate transactions and rollbacks https://www.anujvarma.com/nhibernate-transactions-and-rollbacks/ https://www.anujvarma.com/nhibernate-transactions-and-rollbacks/#respond Wed, 18 Dec 2013 23:47:21 +0000 http://www.anujvarma.com/?p=2205 Introduction The same rollback considerations that apply to normal SQL transactions also apply to nHibernate transactions. Rollback Scenario Suppose you have two SQL Statements – the first one tries to […]

The post nHibernate transactions and rollbacks appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
Introduction

The same rollback considerations that apply to normal SQL transactions also apply to nHibernate transactions.

Rollback Scenario

Suppose you have two SQL Statements – the first one tries to insert (and runs into a primary key violation). The second one tries to update the same record as the first one.

SInce the first one failed, the second one should not proceed with its update. However, if you have the two statements within a transaction, the second one will proceed even though the first one has failed. This is because, on failure of the first statement, no one ENDED the transaction.The transaction still proceeds and executes the second statement.

Here is a code example – sql1 INSERTS a new author (and runs into a constraint), sql2 tries to update the same row:

   1: using (var transaction  = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))

   2: {

   3:  

   4:   var sql1 = "INSERT INTO [authors]([au_id], [au_lname], [au_fname])  VALUES (1, 'Gates', 'Bill');"

   5:   session.CreateSQLQuery(sql1);

   6:  

   7:   var sql2 = "UPDATE authors SET    au_fname = 'anuj' WHERE au_id = 1" 

   8:   session.CreateSQLQuery(sql2);

   9:  

  10:   transaction.commit();

  11: }

The workaround

In case of an exception (caught within a try-catch), rollback the transaction.

   1: try{

   2:     using (var transaction  = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)) 

   3:    {

   4:  

   5:     var sql1 = "INSERT INTO [authors]([au_id], [au_lname], [au_fname])  VALUES (1, 'Gates', 'Bill');"

   6:     session.CreateSQLQuery(sql1);

   7:  

   8:     var sql2 = "UPDATE authors SET    au_fname = 'anuj' WHERE au_id = 1" 

   9:     session.CreateSQLQuery(sql2);

  10:  

  11:     transaction.commit();

  12:    } // close using

  13:   } // close try

  14:   catch(Exception e)

  15:   {

  16:     transaction.Rollback();

  17:     session.Clear(); 

  18:   }

Recommended Pattern for nHibernate Transactions

As per nHibernate’s documentation (and Hibernating Rhino’s), as long as you stick to the usings as shown below, the cleanup will automatically happen during the dispose() (for the transaction and the session). The rollbacks will occur as part of the cleanup – so there isn’t a reason for explicitly rolling back – as long as you use the pattern below.

   1: using(var session = sessionFactory.OpenSession()) 

   2: using(var tx = session.BeginTransaction()) 

   3: { 

   4:     // execute code that uses the session 

   5:     tx.Commit(); 

   6: }

Summary

nHibernate transactions should ideally be surrounded by a try-catch statement – and rolled back in case of exception. In addition, the transaction should always be started with a using( statement – to ensure correct disposal.

The post nHibernate transactions and rollbacks appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
https://www.anujvarma.com/nhibernate-transactions-and-rollbacks/feed/ 0
Fluent nHibernate setting database transaction isolation level https://www.anujvarma.com/fluent-nhibernate-setting-database-transaction-isolation-level/ https://www.anujvarma.com/fluent-nhibernate-setting-database-transaction-isolation-level/#respond Mon, 16 Dec 2013 23:40:00 +0000 http://www.anujvarma.com/?p=2196 Introduction Normally, if you do NOT specify the isolation level for an nHiberante transaction, it will remain undefined. This is bad for many reasons – the primary one being that […]

The post Fluent nHibernate setting database transaction isolation level appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
Introduction

Normally, if you do NOT specify the isolation level for an nHiberante transaction, it will remain undefined. This is bad for many reasons – the primary one being that SQL Server does not know what to do with undefined and has to revert to its own default setting (READCOMMITTED). This is cumbersome – since SQL Server has to do this EVERY single time.  So, you need to figure out a way to explicitly set the isolation level to something other than undefined.

Option 1 – Globally set it – during the configuration

Setting it globally seems to be the logical choice. However, for some reason, Fluent nHibernate did not pick up the global setting. In Fluent nHibernate, there is a database property that one can try setting as follows:

var config = Fluently.Configure()

               .Database(

                   MsSqlConfiguration.MsSql2008.Raw("connection.isolation", "READCOMMITTED")

This, however did not seem to work (the database still sees the transaction as ‘undefined’).

Option 2 – In Code (Set it at the start of the transaction)

The surefire way to accomplish this is to explicitly set the isolation level at the start of the transaction :

session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)

For e.g. – the start of your transaction may look like this:

var session = SessionManager.GetSession();

  using (var transaction  = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))

{ // LINQ query 

}

Yes – this means doing a global Search and Replace for all your BeginTransactions to BeginTransaction(IsolationLevel.ReadCommitted).

On nHibernate’s Transaction.Commit

Surround your commits with a try-catch, so you can rollback the transaction (after all, that is why you are IN a transaction in the first place – so you can rollback if something goes wrong).

   1: try

   2: { 

   3:     transaction.Commit();

   4: }

   5: catch (Exception ex)

   6: {

   7:     transaction.Rollback();

   8:     throw;

   9: } 

Summary

An attempt to set the isolation level globally – via the startup configuration setting for Fluent nHibernate did not seem to work. However, setting it in code, at the start of each transaction – i.e. – at every BeginTransaction – seemed to do the trick. The isolation level correctly shows up (in hibernating rhinos profiler) as READCOMMITTED.

The post Fluent nHibernate setting database transaction isolation level appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
https://www.anujvarma.com/fluent-nhibernate-setting-database-transaction-isolation-level/feed/ 0
Troubleshooting nHibernate Performance https://www.anujvarma.com/troubleshooting-nhibernate-performance/ https://www.anujvarma.com/troubleshooting-nhibernate-performance/#respond Thu, 21 Nov 2013 22:39:00 +0000 http://www.anujvarma.com/?p=1516 Introduction nHibernate is still one of the most popular ORM layers in use today. It provides support for collections, advanced querying, caching, statement batching, automatic change tracking for entities and […]

The post Troubleshooting nHibernate Performance appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
Introduction

nHibernate is still one of the most popular ORM layers in use today. It provides support for collections, advanced querying, caching, statement batching, automatic change tracking for entities and more, making it one of more mature ORM layers in use. However, several projects that I have been involved with seem to point fingers at nHibernate’s performance. This post summarizes some of my findings from investigating bottlenecks, misconfigurations and known nHibernate gotchas.  If you have additional nHibernate performance tweaks, please feel free to provide feedback.

Symptoms

You have probably already run some type of load test (if you would like to get started with load testing, try this post) – which indicates slow response times with increasing user load. Some symptoms that n-Hibernate may be a problem include:

  1. Query execution times in excess of 1 second (use the ‘profiler’ below to identify your bottleneck) .
  2. Frequent deadlock errors thrown by underlying database. In SqlServer , they may look like (note: Here is a post discussing how to quickly identify such sql server deadlocks).
Transaction (Process ID xx) was deadlocked on {xxx} resources with another process 
and has been chosen as the deadlock victim. Rerun the transaction. 

Where to look first ? (nHibernate’s generated sql queries)

You want to get an estimate of the queries that nHibernate is sending to the database – and how long those queries are taking to execute. I don’t know of a better tool than Hibernating Rhinos nHibernate profiler.

Here are some of the things the tool will tell you:

  1. what the underlying sql query was – and how long it took to execute. It shows the execution times of both the database as well as total execution time (that includes nHibernate’s overhead)
  2. Which sessions are opened by nHibernate as your request is sent. And which queries are part of each session.

Once you have an idea of the more expensive queries, there are a few things you can do to fix their performance:

    
    

nhibernateprofiler

Use FetchMode.JOIN

Without the JOIN, your query will get broken down into multiple smaller queries – each of which will require nHibernate to track each of the entities. This is overall more expensive than a single JOIN  – which is what you probably intended in the first place. To keep your JOIN intact, use NHibernate.FetchMode.Join in the Criteria.SetFetchMode as shown below.

criteria.CreateAlias("Products", "SingleProduct", JoinType.LeftOuterJoin)—> NOTE the JOINCriteria.SetFetchMode("SingleProduct", NHibernate.FetchMode.Join) –> NOTE THE JOIN (Without this join, this will translate to multiple fetches i.e. multiple round trips)

Projection(Projections.Projectionist() _

Add(Projections.GroupProperty("Id"), "Id")

 .Add(Projections.GroupProperty("Number"), "Number") 

Get rid of the XML (Use Fluent nHibernate – nuGet package)

nHibernate maintains mappings in XML files. This slows down startup of nHibernate – and is also error-prone (since the compiler has no idea if your XML file has newly renamed properties). Fluent solves both of these problems by eliminating the XML files altogether. The mappings are moved to actual code and are compiled along with the rest of your application – providing a fail-safe check at compile time (to pick up renamed, changed properties). Here is what a sample fluent mapping in c# source looks like (you do not need to do any of this manually, Fluent generates these mappings for you):

public AMap()

{

  /* mapping for id and properties here */

  HasOne(x => x.child)

      .Cascade.All();

}

 

public BMap()

{

  /* mapping for id and properties here */

  References(x => x.parent)

      .Unique();

}

nHibernate Transactions

Transactions – By default, if you do not set an isolation level on your transactions, the isolation level will be ‘undefined’. This tells your database to use its default, IMPLICIT transactions – which it has to REVERT to – for every single query that nHibernate sends it (this article discusses this in detail). To set a specific isolation level, just set the property in your nHibernate’s configuration section in your web (or app) .config.

<property name="connection.isolation">ReadCommitted</property>

Transactions Summary – Always use transactions, always define a transaction isolation level (if you are unsure, READCOMMITTED is a good, middle road option).

nHibernate Sessions

What is session flushing ?

A session will not write to the database every time something is changed. In order to achieve better performance, database access is usually delayed until the last possible moment. This avoids unnecessary database calls, i. e. when multiple fields of a persistent objects are changed within a session. This synchronization with the database is called flushing. 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.

Read this post about dealing with nHibernate sessions – and why you should not be performing multiple operations inside a session anyway.

Manual Session Flushing

Flushing the cache is a known source of performance issues in nHibernate.

To see if flushing is the source of your problems, try the following:

var session = SessionManager.GetSession();

 

// Right before you begin your transaction, flush the session and turn off automatic flushing

session.Flush();

session.FlushMode = NHibernate.FlushMode.Never;

 

using (var transaction = session.BeginTransaction())

{

    // your ICriteria , linq query

    //....

    //....

    //....

 

    session.Save(nomination);

    

    // Before committing (and after saving your session), turn on automatic session flushing 

    session.FlushMode = NHibernate.FlushMode.Auto;

    transaction.Commit();

}

So, before you begin your transaction, do a manual flush (session.Flush()) and turn off auto flushing (FlushMode.Never). Then, after you save your session and before you commit your transaction, turn auto flushing back on.

Use Lazy Loading

  • In Fluent-nHibernate, you would use the  .eager property in code as shown below
var user = session.QueryOver<User>()

                  .Fetch(u => u.Comments)

                  .Eager

                  .List()

                  .Where(u => u.Id == userId)

                  .FirstOrDefault();

  • In non-fluent nHibernate, you can do this using the following (Default-lazy = true):
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="@core.assembly@"

 default-access="nosetter.camelcase-underscore" default-lazy="true">

Singleton Session Manager

Make sure the Session Manager you are using is a singleton (read ‘singleton pattern in C#’, if you are new to the Singleton Pattern). Creating multiple instances of the session manager is not required – and can use up a lot of memory – since nHibernate uses a session for each unit of work.

 

    public class MySessionManager

    {

        private static ISessionFactory _sessionFactory;

 

        public ISession OpenSession()

        {

            lock (factorylock)

            {

                if (_sessionFactory == null)

                {

                    var cfg = Fluently.Configure().

                       Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).

                       Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());

                    _sessionFactory = cfg.BuildSessionFactory();

                    BuildSchema(cfg);

                }

            }

            return _sessionFactory.OpenSession();

        }

        private static void BuildSchema(FluentConfiguration configuration)

        {

            var sessionSource = new SessionSource(configuration);

            var session = sessionSource.CreateSession();

            sessionSource.BuildSchema(session);

        }

    }

Summary

nHibernate is a powerful and mature ORM  layer which is possibly the most popular ORM within the .NET community. However, if used incorrectly, it can be the source of a variety of performance bottlenecks. This post describes some of nHibernate’s common performance issues – along with solutions.

The post Troubleshooting nHibernate Performance appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
https://www.anujvarma.com/troubleshooting-nhibernate-performance/feed/ 0
nHibernate–manual session flushing https://www.anujvarma.com/nhibernatemanual-session-flushing/ https://www.anujvarma.com/nhibernatemanual-session-flushing/#comments Wed, 13 Nov 2013 23:51:35 +0000 http://www.anujvarma.com/?p=1757 An nHibernate session maintains all changes to the object model. At some point, it needs to synchronize these changes with the database. It can either do these constantly (as and […]

The post nHibernate–manual session flushing appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
An nHibernate session maintains all changes to the object model. At some point, it needs to synchronize these changes with the database. It can either do these constantly (as and when it encounters a new change in the object model) – or it can wait till it has a whole batch of changes to commit. The latter is an obvious choice – since it avoids multiple database roundtrips. This ‘synchronization’ is called flushing and it happens at various points in a session’s lifecycle. While it is a good thing, if you have TOO MUCH flushing, you may end up with a performance degradation.

For example, if you have a complex query (which gets broken into many smaller queries by nHibernate), you drastically increase the number of times that session.flush() is called by nHibernate. The problem is :

Each session.flush() call is very expensive.

For your complex queries, you may be looking at a few dozen times that this session.flush() call takes place. This really slows down the round trip query execution time (although in reality, the actual SQL execution has nothing to do with it – it is simply nHibernate’s bookkeeping).

Turn off automatic flushing

This is the single , most important performance improvement you can make in nHibernate. Turning automatic flushing off means you will manually have to decide when and where to flush(). This is simple – just before you start your transaction make sure everything is in sync by flushing once. Now turn off automatic flushing. And right before you are ready to commit your transaction (after you have saved your session), go ahead and turn flushing back on. Here is a sample :

Just before you start your transaction

  1. Manually flush and
  2. Turn off auto flushing

var session = SessionManager.GetSession();

 

            // Right before you begin your transaction, flush the session and turn off automatic flushing

            session.Flush();

            session.FlushMode = NHibernate.FlushMode.Never;

 

            using (var transaction = session.BeginTransaction())

            {

            

Just before you commit,

  1. Turn automatic flushing back on
session.Save(nomination);

 

               // turn on automatic session flushing 

               session.FlushMode = NHibernate.FlushMode.Auto;

               transaction.Commit();

What can go wrong?

Remember, you are temporarily suspending synchronizing the database with your object changes. This is not an issue for your retrieval (get) queries, but for saves, updates, deletes – you need to watch out for specific scenarios where you may have transient data (data that is not yet committed – but you try to access anyway). An example of such a transient piece of data is a private property ID (private so that the database autogenerates the ID). If you have an ID that is to be autogenerated – and you try to access that ID before the commit takes place, you will end up in this ‘exception’ scenario. Suppose your logic entails creating a new Product (say a new Financial Product Offering) – and then associating existing customers with it (perhaps as PROSPECTS for this product). Since your productID is not yet committed, associating the customers will not work – and will throw an exception of the following type:

nhibernate_transient_exception

NHibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing or set cascade action for the property to something that would make it autosave. Type:

All this means is that nHibernate does not know what to do with the object changes (since flushing has been turned off). To counter this, you must revisit your business logic and try and figure out why you needed to access something that hadn’t been committed yet. If possible, change the business logic. If not possible, then simply remove the manual flushing code above and revert to automatic flushing. This scenario, though possible, is more of an exception than the rule – and generally speaking, the manual flushing is a safe change to make.

In addition to revisiting your business logic, one recommended change (for your transaction.commit()) is to surround it with a try-catch. The try catch will allow a rollback in case you end up with any failed parts within your transaction. All you need is :

   1:  

   2: try

   3: { 

   4:      transaction.Commit();

   5: }

   6: catch (Exception ex)

   7: {

   8:     transaction.Rollback();

   9:     throw;

  10: } 

After all, rollbacks are the reason you are using transactions in the first place. If something goes wrong, you have the option of rolling back the transaction to avoid inconsistent states.

Summary

There are a few areas where nHibernate settings can affect your data tier performance. The most significant one that I discovered (during a production troubleshooting assignment of a web app) was this automatic and frequent session  flushing. This can be easily circumvented by a few lines of code change.  It does speed things up – but comes with a potential drawback – which affects saves and updates  (not the retrievals). The saves and updates can possibly run into a situation where nHibernate does not know what to do with a transient object. It throws a meaningful exception – which can be addressed using the suggestions above.

In spite of this potential drawback, manual session flushing is something I would still recommend – due to the significant performance gain. The files affected by the potential drawback can be easily addressed by either disabling manual flushing – or reworking the business logic that causes the exception to occur.

The post nHibernate–manual session flushing appeared first on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.

]]>
https://www.anujvarma.com/nhibernatemanual-session-flushing/feed/ 3