Stateless sessions

NHibernate sessions are stateful by default. In other words, they maintain the state of the entities that pass through them. During the course of execution of any functionality, following is what usually happens if you are using a NHibernate session:

  1. You open a new session.
  2. You begin a transaction on this session.
  3. You load some entities from the database using the session.
  4. The entities loaded are tracked in the identity map (session level cache), in case they are queried again.
  5. The entities are also kept in the second level cache if it is configured.
  6. You then update few properties on the entities.
  7. You then commit your NHibernate transaction to signal to NHibernate to persist your in-memory changes to the database (remember transitive persistence?).
  8. NHibernate uses dirty checking to find out which of the entities in the session have changed and only persists the changes to the database.
  9. As part of above, NHibernate also cascades the database operations down to the collections/associations as per mapping configuration.
  10. NHibernate updates the copies kept in the second level cache.

Rather NHibernate is doing a lot of maintaining and tracking of entity instances internally. This heavy-lifting done by NHibernate means that we do not have to write extensive code to track the state of each entity and maintain entities already loaded from the database in the same transaction. But this also means that querying or persisting data gets slowed down. This is obvious. More work NHibernate does while loading or persisting data, the longer it is going to take to do the actual work. For usual business operations, this overhead is acceptable. So that, the advantages of this internal working of NHibernate greatly outweighs the overhead introduced.

But if you are required to load a large number of entities from the database, perform some operations on them, and save them back to the database, then above does not scale well. We have discussed the batching techniques in Chapter 7, Optimizing Data Access Layer, which we might want to use here. But even those solutions do not scale well when it comes to big numbers. OutOfMemoryExceptions would be too common if we try to use ISession to deal with thousands of entities at the same time. NHibernate team recognized this problem and they have provided an alternate, stateless implementation of ISession, aptly named IStatelessSession. Stateless session works exactly the same way as a normal session except for the lack of some features described as follows:

  • No identity map leading to the data aliasing effect. If the same entity is retrieved twice, two copies of it are created in memory. There are cases when stateless session maintains a temporary identity map to de-duplicate entities, for example, when eager fetching is used. It would be useful to assume that we may end up with duplicate entity instances in memory if we are using stateless session.
  • No write-behind or dirty checking. You need to explicitly tell NHibernate which entities to save/update/delete.
  • No interaction with the second level cache. Also means that you cannot use query caching.
  • Operations are not cascaded down to associations or collections. Any changes made to the parent entity that need to be cascaded down to associations or collections have to be done manually and explicitly.
  • No automatic deletion of the orphan child records.
  • Event system of NHibernate is completely bypassed. So if you are hooking into events to add audit information then make sure you have alternatives in place to work with the stateless sessions.

This absence of features is what gives the stateless session its performance and memory boost.

In order to open a stateless session, you can call the ISession.OpenStatelessSession method. Rest of the semantics around using a stateless session are the same as normal session except for the following two:

  • There is no Save method. In order to persist a transient entity instance, we can use the Insert method.
  • There is no notion of a transitive persistence as change tracking does not work. So for any updates to the persistent entities, the Update method has to be called explicitly.

In a nutshell, keep in mind that you need to explicitly specify how you want to add/update/delete the entities. NHibernate is not doing anything for you. So use it but with extreme care and make sure you test your code thoroughly.

Note

Most likely scenarios where you would want to use the stateless session is bulk import kind of scenario where you are being asked to load thousands of records in to the database at one go. Ideally, you should be using bulk import features natively supported by your database. The only reason you might need to use a stateless session is when the import process involves executing domain logic which you do not want to duplicate in the native import process of your database. But remember that stateless sessions, though faster than the normal sessions, are still slower than executing a stored procedure or native bulk import. So choose the right tool for the job.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.104.95