什么是NHibernate一级缓存
NHibernate一级缓存即ISession缓存,ISession缓存属于事务级缓存,是NHibernate内置的。ISession缓存中的数据只在本ISession周期内使用。
ISession实例创建后即可使用ISession缓存。此后,ISession实例操作数据时,首先查询内置缓存,如果ISession缓存中存在相应数据,则直接使用缓存数据。如果不存在,则查询数据库并把其结果存在缓存中。
一、一级缓存就在身边
1) 当查询条件相同,且是同一个ISession时由NHibernate自动调用缓存
a) 在DAL.Test中编写代码如下:
[Test]
public void SessionTest()
{
Console.WriteLine("第一次加载");
Customer customer_1 = session.Get<Customer>(1);
Console.WriteLine("第二次加载");
Customer customer_2 = session.Get<Customer>(1);
}
b) 跟踪NHibernate生成SQL的结果
------ Test started: Assembly: DAL.Test.dll ------
第一次加载
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
第二次加载
1 passed, 0 failed, 0 skipped, took 4.92 seconds (NUnit 2.5.1).
我们可以看到,NHibernate只在第一次加载Customer对象时查询了数据库,而第二次加载时并没有生成相应的SQL语句,这是因为SessionTest()函数中的session在第一次加载后没有被销毁的情况下,对Customer进行第二次加载,那么NHibernate就会先到未被销毁的session中去查询,如果存在则直接从session中返回结果,不存在时,才生成SQL语句并到数据库中查询。
2) 这里是同一个ISession,不同的查询条件
a) 为了证明,修改程序如下:
[Test]
public void SessionTest()
{
Console.WriteLine("第一次加载");
Customer customer_1 = session.Get<Customer>(1);
Console.WriteLine("第二次加载");
Customer customer_2 = session.Get<Customer>(2);
}
b) 跟踪NHibernate生成SQL的结果
------ Test started: Assembly: DAL.Test.dll ------
第一次加载
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
第二次加载
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 2
1 passed, 0 failed, 0 skipped, took 5.47 seconds (NUnit 2.5.1).
这里果然生成了两个SQL语句,因为CustomerId为2的对象或者叫结果集在session中不存在,所以必须再到数据库中去查询。
3) 这里是同样的查询条件,不同的ISession
a) 为了证明,修改程序如下:
[Test]
public void SessionTest()
{
using (ISession _session = sessionHelper.GetSession())
{
Console.WriteLine("第一次加载");
Customer customer_1 = _session.Get<Customer>(1);
}
using (ISession _session = sessionHelper.GetSession())
{
Console.WriteLine("第二次加载");
Customer customer_2 = _session.Get<Customer>(1);
}
}
b) 跟踪NHibernate生成SQL的结果
------ Test started: Assembly: DAL.Test.dll ------
第一次加载
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
第二次加载
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
1 passed, 0 failed, 0 skipped, took 4.95 seconds (NUnit 2.5.1).
二、ISession.Get和ISession.Load的区别
1) ISession.Get
a) 编写代码如下:
[Test]
public void SessionTest()
{
Console.WriteLine("获取持久化实例:");
Customer customer = session.Get<Customer>(1);
Console.WriteLine("访问customer属性:customerId=" + customer.CustomerId);
Console.WriteLine("访问customer属性:firstName=" + customer.Firstname);
}
b) 结果如下:
------ Test started: Assembly: DAL.Test.dll ------
获取持久化实例:
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
访问customer属性:customerId=1
访问customer属性:firstName=luo
1 passed, 0 failed, 0 skipped, took 4.92 seconds (NUnit 2.5.1).
2) ISession.Load
a) 修改代码如下:
[Test]
public void SessionTest()
{
Console.WriteLine("获取持久化实例:");
Customer customer = session.Load<Customer>(1);
Console.WriteLine("访问customer属性:customerId=" + customer.CustomerId);
Console.WriteLine("访问customer属性:firstName=" + customer.Firstname);
}
b) 结果如下:
------ Test started: Assembly: DAL.Test.dll ------
获取持久化实例:
访问customer属性:customerId=1
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
访问customer属性:firstName=luo
1 passed, 0 failed, 0 skipped, took 5.19 seconds (NUnit 2.5.1).
注意:上面两个方法和结果的比较,Get方法一被调用,立即产生SQL语句去查询数据库,而Load方法却是到了需要去取查询结果时才产生SQL去查询数据库,这就是它们两个最大的区别吧!
三、一级缓存管理
1) ISession缓存管理的相关方法
a) ISession.Evict(object):从缓存中删除指定实例。
b) ISession.Clear():清空缓存。
c) ISession.Contains(object):检查缓存中是否包含指定实例。
2) 编写代码如下:
[Test]
public void SessionTest()
{
Customer customer_1, customer_2;
customer_1 = session.Get<Customer>(1);
customer_2 = session.Get<Customer>(2);
Console.WriteLine("customer_1:" + session.Contains(customer_1).ToString());
Console.WriteLine("customer_2:" + session.Contains(customer_2).ToString() + "/r/n");
session.Evict(customer_1); //清除某个缓存
Console.WriteLine("customer_1:" + session.Contains(customer_1).ToString());
Console.WriteLine("customer_2:" + session.Contains(customer_2).ToString() + "/r/n");
session.Clear(); //清除该ISession中的所有缓存
Console.WriteLine("customer_1:" + session.Contains(customer_1).ToString());
Console.WriteLine("customer_2:" + session.Contains(customer_2).ToString() + "/r/n");
}
3) 结果如下:
------ Test started: Assembly: DAL.Test.dll ------
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 1
NHibernate: SELECT customer0_.CustomerId as CustomerId4_0_, customer0_.Firstname as Firstname4_0_, customer0_.Lastname as Lastname4_0_ FROM Customer customer0_ WHERE customer0_.CustomerId=@p0;@p0 = 2
customer_1:True
customer_2:True
customer_1:False
customer_2:True
customer_1:False
customer_2:True
1 passed, 0 failed, 0 skipped, took 4.89 seconds (NUnit 2.5.1).