在本章中,我们将介绍延迟加载功能.默认情况下这是一个完全不同的概念,NHibernate没有延迟加载,例如,如果您加载客户,它不会加载所有订单.
订单集合将按需加载.
任何关联,无论是多对一关联或者,默认情况下,集合是延迟加载的,它需要打开ISession .
如果您已关闭会话,或者您已关闭已经提交了你的事务,你可以得到一个懒惰的加载异常,它无法吸引那些额外的对象.
你必须小心延迟加载和多少您实际需要的数据.
您可以关闭整个关联的延迟加载,也可以将lazy等于false,或者也可以指定提取策略.
这是 Program.cs 文件的实现.
using System; using System.Data; using System.Linq; using System.Reflection; using HibernatingRhinos.Profiler.Appender.NHibernate; using NHibernate.Cfg; 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(); Guid id; using(var session = sessionFactory.OpenSession()) using(var tx = session.BeginTransaction()) { var newCustomer = CreateCustomer(); Console.WriteLine("New Customer:"); Console.WriteLine(newCustomer); session.Save(newCustomer); id = newCustomer.Id; tx.Commit(); } using(var session = sessionFactory.OpenSession()) using(var tx = session.BeginTransaction()) { var reloaded = session.Load(id); Console.WriteLine("Reloaded:"); Console.WriteLine(reloaded); Console.WriteLine("The orders were ordered by: "); foreach (var order in reloaded.Orders) { Console.WriteLine(order.Customer); } tx.Commit(); } Console.WriteLine("Press to exit..."); Console.ReadLine(); } private static Customer CreateCustomer() { var customer = new Customer { FirstName = "John", LastName = "Doe", Points =100, HasGoldStatus = true, MemberSince = new DateTime(2012, 1, 1), CreditRating = CustomerCreditRating.Good, AverageRating = 42.42424242, Address = CreateLocation() }; var order1 = new Order { Ordered = DateTime.Now }; customer.AddOrder(order1); var order2 = new Order { Ordered = DateTime.Now.AddDays(-1), Shipped = DateTime.Now, ShipTo = CreateLocation() }; customer.AddOrder(order2); return customer; } private static Location CreateLocation() { return new Location { Street = "123 Somewhere Avenue", City = "Nowhere", Province = "Alberta", Country = "Canada" }; } private static Configuration ConfigureNHibernate() { NHibernateProfiler.Initialize(); var cfg = new Configuration(); cfg.DataBaseIntegration(x => { x.ConnectionStringName = "default"; x.Driver (); x.Dialect 要理解这一点,让我们运行应用程序并查看NHibernate Profiler.
如您所见,我们有Select From客户,给定一个特定的客户ID,然后我们还有另一个Select From Orders表,当它实际访问该客户的集合时.
所以我们有2次往返数据库.现在,有时,我们想要优化它.为此,我们转到 customer.hbm.xml 文件并添加一个提取策略并要求它进行连接提取.
您可以看到我们没有更改应用程序中的任何代码,我们刚刚在 customer.hbm中添加了一个提取策略. XML 的.让我们再次运行这个应用程序,它的行为方式完全相同.让我们来看看NHibernate Profiler.
之前,程序有两次往返数据库,现在,它只有一个,那是因为它在这里进行左外连接.
我们可以看到它在客户表和订单表之间根据客户ID进行左外连接,因此,它可以一次加载所有这些信息.
我们已经将1次往返保存到数据库中.
缺点是客户信息将会在两行上都是重复的,这就是SQL左外连接的工作方式.
因此,通过提取策略,我们将撤回更多的数据和我们正在保存往返.
您也可以在查询级别执行此操作,所以让我们转到 Program.cs 文件并查看更简单的重新加载例如.
using(var session = sessionFactory.OpenSession()) using(var tx = session.BeginTransaction()) { //var query = from customer in session.Query() // select customer; //var reloaded = query.Fetch(x => x.Orders).ToList(); var reloaded = session.Load (id); Console.WriteLine("Reloaded:"); Console.WriteLine(reloaded); Console.WriteLine("The orders were ordered by: "); foreach (var order in reloaded.Orders) { Console.WriteLine(order.Customer); } tx.Commit(); } 在这里,我们正在由客户负责.现在让我们将其更改为一个查询,我们将使用链接查询,如下面的代码所示.
using(var session = sessionFactory.OpenSession()) using(var tx = session.BeginTransaction()) { var query = from customer in session.Query() where customer.Id == id select customer; var reloaded = query.Fetch(x => x.Orders).ToList().First(); Console.WriteLine("Reloaded:"); Console.WriteLine(reloaded); tx.Commit(); } 我们还要从 customer.hbm.xml 文件中删除提取策略.
让我们再次运行此应用程序,您将看到以下输出.
New Customer:John Doe (00000000-0000-0000-0000-000000000000) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Unspecified) CreditRating: Good AverageRating: 42.42424242 Orders: Order Id: 00000000-0000-0000-0000-000000000000 Order Id: 00000000-0000-0000-0000-000000000000Reloaded:John Doe (6ebacd17-f9ba-4ad8-9817-a5bb01112a5a) Points: 100 HasGoldStatus: True MemberSince: 1/1/2012 12:00:00 AM (Utc) CreditRating: Good AverageRating: 42.4242 Orders: Order Id: 16a6596b-d56e-41c7-9681-a5bb01112a60 Order Id: d41d615b-0f21-4032-81db-a5bb01112a61Pressto exit... 现在让我们看一下NHibernate Profiler,你可以看到我们再次发生这种渴望的连接获取,但这一次,它基于查询.