NHibernate - Load/Get



In this chapter, we will be covering how the Load and Get features are working and how we can use them. These are two very similar APIs provided by ISession for loading an object by primary key.

  • Get − it will return the object or a null.

  • Load − it will return the object or it will throw an ObjectNotFoundException.

Now, why do we have these two different APIs?

Load

  • It's because Load can optimize database round trips much more efficiently.

  • Load actually returns a proxy object and doesn't need to access the database right when you issue that Load call.

  • When you access that proxy, the object doesn't happen to be in the database, it can throw an ObjectNotFoundException at that point.

Get

  • Conversely, with Get because of limitations of the CLR or Common Language Runtime and NHibernate must go to the database immediately, check if the objects are there and return null, if it's not present.

  • It doesn't have the object option of delaying that fetch, that roundtrip to the database to a later time because it cannot return a proxy object and that swapped that proxy object out for a null, when the user actually accesses it.

Let’s have a look into a simple example in which you will see how these are actually used and the difference between Get and Load. We will continue with same domain classes Customers and Orders and similarly the same mapping files from the last chapter.

In this example, we will first use the Get as shown in the following program.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver;
using NHibernate.Linq; 

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var id1 = Guid.Parse("4e97c816-6bce-11e1-b095-6cf049ee52be"); 
            var id2 = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE");
				
            var customer1 = session.Get<Customer>(id1); 
            Console.WriteLine("Customer1 data"); 
            Console.WriteLine(customer1);
				
            var customer2 = session.Get<Customer>(id2); 
            Console.WriteLine("Customer2 data"); 
            Console.WriteLine(customer2); 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() {
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead;
            x.Timeout = 10; 
            x.BatchSize = 10; 
         }); 
         
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

As you can see that we have two Guid ID’s, the first one is a good ID, it's the ID of a customer that we know is in the database. While the second ID is not present in the database. Both these ID’s are passed as a parameter to Get() method and then the result is printed on the console.

When the above code is compiled and executed you will see the following output.

Customer1 data
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

Orders:
   Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
   Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
   Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
   Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
	
Customer2 data
Press <ENTER> to exit...

As you can see that Customer1 data is printed but the Customer2 data is empty, that is because the Customer2 record is not available in the database.

When you run your application again, we can insert a break point before the commit statement and then let’s look at both customers in the Watch window.

Customer2 Record

As you can see that Customer1 data is available, while Customer2 is null and the type is NHibernateDemo.Customer for both.

Now let’s use the Load method instead of Get in the same example as shown in the following code.

using System; 
using System.Data; 
using System.Linq; 
using System.Reflection; 

using HibernatingRhinos.Profiler.Appender.NHibernate; 
using NHibernate.Cfg; 
using NHibernate.Criterion; 
using NHibernate.Dialect; 
using NHibernate.Driver;
using NHibernate.Linq; 

namespace NHibernateDemo { 

   internal class Program { 
	
      private static void Main() { 
		
         var cfg = ConfigureNHibernate(); 
         var sessionFactory = cfg.BuildSessionFactory();
         using(var session = sessionFactory.OpenSession()) 
         
         using(var tx = session.BeginTransaction()) { 
            var id1 = Guid.Parse("4e97c816-6bce-11e1-b095-6cf049ee52be"); 
            var id2 = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE");
				
            var customer1 = session.Load<Customer>(id1); 
            Console.WriteLine("Customer1 data"); 
            Console.WriteLine(customer1);
				
            var customer2 = session.Load<Customer>(id2); 
            Console.WriteLine("Customer2 data"); 
            Console.WriteLine(customer2); 
				
            tx.Commit(); 
         }
			
         Console.WriteLine("Press <ENTER> to exit..."); 
         Console.ReadLine(); 
      }
		
      private static Configuration ConfigureNHibernate() { 
		
         NHibernateProfiler.Initialize(); 
         var cfg = new Configuration(); 
         
         cfg.DataBaseIntegration(x => { 
            x.ConnectionStringName = "default"; 
            x.Driver<SqlClientDriver>(); 
            x.Dialect<MsSql2008Dialect>(); 
            x.IsolationLevel = IsolationLevel.RepeatableRead; 
            x.Timeout = 10;
            x.BatchSize = 10; 
         }); 
			
         cfg.SessionFactory().GenerateStatistics();
         cfg.AddAssembly(Assembly.GetExecutingAssembly()); 
         return cfg; 
      } 
   } 
}

Now let’s run this example and you will see that the following exception is thrown as seen in the screenshot.

Exception Nhibernate Profile

Now if you look at the Watch window, you will see the type is customer proxy for both objects. And you also see the same data for Customer1 on the console window.

Customer1 data
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
   Points: 74
   HasGoldStatus: True
   MemberSince: 4/4/2009 12:00:00 AM (Utc)
   CreditRating: Neutral
   AverageRating: 0

   Orders:
      Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
      Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be 
		
Customer2 data
Advertisements