📅  最后修改于: 2020-11-19 05:39:54             🧑  作者: Mango
在本章中,我们将介绍延迟加载功能。默认情况下,这是一个完全不同的概念,NHibernate不会延迟加载,例如,如果加载客户,则不会加载所有订单。
订单集合将按需加载。
默认情况下,任何关联(无论是多对一还是集合)都是延迟加载的,都需要一个Open ISession 。
如果关闭了会话或提交了事务,则可能会出现延迟加载异常,该异常无法拉入那些其他对象。
您必须注意延迟加载以及实际需要多少数据。
您可以关闭整个关联的延迟加载,也可以将延迟等于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。
正如您所看到的,我们有从特定客户ID的“从客户选择”,然后,当它实际访问该客户的集合时,我们还有另一个“从订单选择”表。
因此,我们有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-000000000000
Reloaded:
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-a5bb01112a61
Press to exit...
现在让我们看一下NHibernate Profiler,您可以看到我们再次渴望进行联接获取,但是这次,它是基于查询的。