NHibernate - Load/Get

在本章中,我们将介绍 Load 和 Get 功能的工作原理以及如何使用它们。这是 ISession 提供的两个非常相似的 API,用于通过主键加载对象。

  • Get − 它将返回对象或 null。

  • Load −它将返回对象,否则将抛出 ObjectNotFoundException

现在,为什么我们有这两个不同的 API?

Load

  • 这是因为 Load 可以更有效地优化数据库往返。

  • Load 实际上返回一个代理对象,并且在您发出该 Load 调用时不需要访问数据库。

  • 当您访问该代理时,该对象恰好不在数据库中,它可以在此时抛出 ObjectNotFoundException。

Get

  • 相反,由于 CLR 或 Common Language Runtime 和 NHibernate 的限制,Get 必须立即转到数据库,检查对象是否存在并返回 null,如果不存在存在。

  • 它没有延迟该提取的对象选项,该往返数据库的时间稍后,因为它无法返回代理对象,并且当用户实际访问它时,该代理对象被替换为空。

让我们看一个简单的例子,您将在其中看到它们实际上是如何使用的,以及 Get 和 Load 之间的区别。我们将继续使用相同的域类 CustomersOrders 以及上一章中的相同映射文件。

在此示例中,我们将首先使用 Get,如以下程序所示。

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; 
      } 
   } 
}

如您所见,我们有两个 Guid ID,第一个是好 ID,它是我们知道在数据库中的客户的 ID。而第二个 ID 不存在于数据库中。这两个 ID 都作为参数传递给 Get() 方法,然后将结果打印在控制台上。

编译并执行上述代码后,您将看到以下输出。

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...

如您所见,Customer1 数据已打印,但 Customer2 数据为空,这是因为数据库中没有 Customer2 记录。

再次运行应用程序时,我们可以在提交语句之前插入一个断点,然后让我们在 Watch 窗口中查看两个客户。

Customer2 Record

如您所见,Customer1 数据可用,而 Customer2 为空,并且两者的类型均为 NHibernateDemo.Customer

现在让我们在同一个示例中使用 Load 方法代替 Get,如以下代码所示。

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; 
      } 
   } 
}

现在让我们运行这个示例,您将看到屏幕截图中抛出了以下异常。

Exception Nhibernate Profile

现在,如果您查看 Watch 窗口,您将看到两个对象的类型都是客户代理。并且您还会在控制台窗口中看到 Customer1 的相同数据。

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