开发手册 欢迎您!
软件开发者资料库

NHibernate -延迟加载

NHibernate延迟加载 - 从概述,架构,Orm,环境设置,入门,基本Orm,基本Crud操作,Profiler,添加Intelliesnse到映射文件,数据类型映射,配置,覆盖配置,批量大小,缓存,映射来学习NHibernate组件,关系,集合映射,级联,延迟加载,反向关系,加载/获取,Linq,Hibernate查询语言,条件查询,QueryOver查询,本机Sql,流利Hibernate。

在本章中,我们将介绍延迟加载功能.默认情况下这是一个完全不同的概念,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.

Customers Collection

如您所见,我们有Select From客户,给定一个特定的客户ID,然后我们还有另一个Select From Orders表,当它实际访问该客户的集合时.

所以我们有2次往返数据库.现在,有时,我们想要优化它.为此,我们转到 customer.hbm.xml 文件并添加一个提取策略并要求它进行连接提取.

                                                                                                                                                                                              

您可以看到我们没有更改应用程序中的任何代码,我们刚刚在 customer.hbm中添加了一个提取策略. XML 的.让我们再次运行这个应用程序,它的行为方式完全相同.让我们来看看NHibernate Profiler.

Customer Profile

  • 之前,程序有两次往返数据库,现在,它只有一个,那是因为它在这里进行左外连接.

  • 我们可以看到它在客户表和订单表之间根据客户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-a5bb01112a61Press  to exit...

现在让我们看一下NHibernate Profiler,你可以看到我们再次发生这种渴望的连接获取,但这一次,它基于查询.

Join Fetch