Using stateless sessions

When processing large amounts of data, you can usually improve performance by using an API that's closer to the bare metal, often times trading off some higher-level features in the process. In NHibernate, this high performance, low-level API is the stateless session.

Here we'll use a stateless session to update our movie prices.

Getting ready

Complete the Getting Ready instructions at the beginning of Chapter 4, Queries.

How to do it...

  1. Add a new folder named Stateless to the QueryRecipes project.
  2. Create a class named Recipe in the folder:
    using NH4CookbookHelpers.Queries;
    using NH4CookbookHelpers.Queries.Model;
    using NHibernate;
    using NHibernate.Linq;
    using System;
    using System.Linq;
    
    namespace QueryRecipes.Stateless
    {
      public class Recipe : QueryRecipe
      {
        
      }
    }
  3. To create some data with which to work, add the following method to your Recipe class:
    protected override void AddData(ISessionFactory sessionFactory)
    {
      using (var session = sessionFactory.OpenStatelessSession())
      {
        using (var tx = session.BeginTransaction())
        {
          for (int i = 0; i < 1000; i++)
            session.Insert(new Movie()
            {
              Name = "Movie " + i,
              Description = "A great movie!",
              UnitPrice = 14.95M,
              Director = "Johnny Smith"
            });
          tx.Commit();
        }
      }
    }
  4. Next, let's update our movie prices and add the following method to the Recipe class:
    protected override void Run(ISessionFactory sessionFactory)
    {
      using (var session = sessionFactory.OpenStatelessSession())
      {
        using (var tx = session.BeginTransaction())
        {
          var movies = session.Query<Movie>().ToList();
          foreach (var movie in movies)
          {
            UpdateMoviePrice(movie);
            session.Update(movie);
          }
          tx.Commit();
        }
      }
    }
  5. Finally, add our UpdateMoviePrice method:
    static Random rnd = new Random();
    
    static void UpdateMoviePrice(Movie movie)
    {
      // Random price between $9.95 and $24.95
      movie.UnitPrice = (decimal) rnd.Next(10, 26) - 0.05M;
    }
  6. Run the application and start the Stateless recipe.

How it works...

Using a stateless session, we create 1000 movies. Stateless sessions don't implement transactional write-behind, meaning that the SQL statements are not delayed until we commit the transaction. However, if we have turned on batching, they don't happen immediately either. Instead the insert statements are queued up and sent all together. If batching is turned off, these would be sent one at a time immediately with each call to session.Insert.

Next, we fetch all of our movies from the database with the help of a query. These movies are detached; they are not associated with a session; entities can't be associated with stateless sessions. In this case, we load our entities with a query or the Get method.

Since stateless sessions don't implement automatic dirty checking, we have to call session.Update to save our changes to each movie.

There's more...

A stateless session is essentially a stripped-down version of a standard NHibernate session. It doesn't use a first-level cache or perform automatic dirty checking and it doesn't support lazy loading. In fact, it doesn't even keep references to entities, which helps avoid memory leaks when processing thousands of entities. Cascading is ignored and you must explicitly insert, update, or delete each entity, one at a time. Stateless sessions also bypass the second-level cache, event listeners, and interceptors.

Despite these limitations, stateless sessions are very useful in high-performance batch processing situations where you need to work with real objects. When you can work with the raw data, there are usually even better alternatives, such as plain old SQL, HQL bulk actions, SqlBulkCopy, or ETL tools. For the plain old SQL route, simply access the ADO.NET connection object from session.Connection and write your ADO.NET code as you normally would.

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

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