丹尼大叔

数学专业毕业,爱上编程的大叔,兴趣广泛。使用博客园这个平台分享我工作和业余的学习内容,以编程交友。有朋自远方来,不亦乐乎。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

摘要

Nhibernatea缓存非常强大,按照缓存存储在Session对象还是SessionFactory对象分为一级缓存和二级缓存。

一级缓存存在于Session对象里,也叫Session缓存,由Session进行管理。一级缓存是NHibernate内置的缓存。

二级缓存存在于SessionFactory对象里,也叫SessionFactory缓存,由SessionFactory进行管理,并且有大量的第三方dll对他进行扩展,他是一种“可插拔式”的缓存。

这一节主要讲一级缓存,后面一篇文章介绍二级缓存。

1. 一级缓存介绍

NHibernate一级缓存原理:

  • NHibernate的Session对象在自己的内存中开辟”内存池“,这个“内存池”里存储持久化状态的NHibernate实体对象。这个内存池的结构是一个类似于IdentityMap的键值对集合,可以看做是.Net的字典对象。这个“内存池”就是一级缓存。
  • 字典的键就是主键值,字典的值就是持久化对象。如果两个对象的主键值相等,则认为两对象相等。因此,如果映射结构里没有设置主键,NHibernate就无法管理Session的缓存,会报Exception。
  • NHibernate查询从数据库里查询出NHibernate实体对象变成持久化状态,放在Session持久化对象缓存池里,之后访问该对象的时候就自动从缓存里读取。
  • 一个NHibernate持久化状态实体对象只缓存在自己所属的Session里。

也就是说:

  • 如果同一个Session两次查询同一个NHibernate实体,则第一次查询后将结果存入该session的缓存里,第二次查询使用Session缓存里的记录,只在第一次查询的时候执一次数据库查询。
  • 如果两个Session对象查询同一个NHibernate实体则需要两次查询数据库,执行两次数据库查询。

2. 程序演示

1)在同一个session执行两次相同记录的查询

修改Main函数代码

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             //在同一个session里执行两次相同记录的查询
 6             using (var session = SessionFactory.OpenSession())
 7             {
 8                 var customer1 = session.Get<Customer>(1);
 9                 var customer2 = session.Get<Customer>(1);
10             }
11 
12             Console.WriteLine("Completed");
13             Console.ReadLine();
14         }

打开NHibernateProfile监控,执行程序,得到结果,看到只执行了一次SQL查询

2)在不同session中执行两次相同记录的查询

修改Main函数代码

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             //在同一个session执行两次相同记录的查询
 6             using (var session = SessionFactory.OpenSession())
 7             {
 8                 var customer = session.Get<Customer>(1);
 9             }
10 
11             using (var session = SessionFactory.OpenSession())
12             {
13                 var customer = session.Get<Customer>(1);
14             }
15 
16             Console.WriteLine("Completed");
17             Console.ReadLine();
18         }

ctrl+x清空NHibernateProfile监控结果,执行程序,得到结果,执行了两次SQL查询。

3. 一级缓存补充

ISession接口为我们提供了一些方法来显式管理一级缓存。

  • ISession.Evict(object):从缓存中删除指定实例
  • ISession.Clear():清空缓存
  • ISession.Contains(object):检查缓存中是否包含指定实例

 

posted on 2016-07-02 17:34  丹尼大叔  阅读(851)  评论(2编辑  收藏  举报