NHibernate之一级缓存(第十篇)
NHibernate的一级缓存,名词好像很牛B,很难。实际上就是ISession缓存。存储在ISession的运行周期内。而二级缓存则存储在ISessionFactory内。
一、ISession一级缓存测试
ISession默认开启一级缓存,不需要任何配置。ISession缓存在ISession创建后就可以使用,以后每次通过此ISession操作数据时,ISession会检测自身是否缓存有相应的数据,如果有则直接返回。如果没有,这时才查询数据库返回,同时缓存到ISession。当释放ISession实例的时候,缓存自动销毁。
示例:
首先我们先开启配置文件中的show_sql节点:
<property name="show_sql">true</property> //开启这个对本缓存测试没影响,只是看看效果
PersonDao.cs
public class PersonDao
{
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
ISession session; public PersonDao()
{
session = sessionFactory.OpenSession();
}
public PersonModel GetPersonById(int Id)
{
PersonModel p = session.Get<PersonModel>(Id);
return p;
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
PersonDao dao = new PersonDao();
//第一次读取
PersonModel p1 = dao.GetPersonById();
Console.WriteLine(p1.Id + " " + p1.Name);
//第二次读取
PersonModel p2 = dao.GetPersonById();
Console.WriteLine(p2.Id + " " + p2.Name); Console.ReadKey();
}
}
输出:

我们看到只有第一次查询执行了SQL语句,第二次并没有执行任何语句。这点从SQL Server Profiler中也可监控到。

在两个会话中获得同一实例
下面我们把
sessionFactory.OpenSession();
这行代码放到方法里面会怎么样呢?
public PersonModel GetPersonById(int Id)
{
ISession session = sessionFactory.OpenSession();
PersonModel p = session.Get<PersonModel>(Id);
return p;
}
输出结果如下:

留意到每OpenSession一次,缓存就没有了。OpenSession一次,NHibernate会自动释放原有的ISession对象。
看到这里,你应该懂得注意下自己代码的写法了。
二、ISession.Get()与ISession.Load()的区别
不想废话,十几行代码说明问题:
static void Main(string[] args)
{
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
ISession session = sessionFactory.OpenSession(); Console.WriteLine("Get之前");
PersonModel pGet = session.Get<PersonModel>();
Console.WriteLine("Get之后");
Console.WriteLine("读取名字" + pGet.Name);
Console.WriteLine("=====================================");
Console.WriteLine("Load之前");
PersonModel pLoad = session.Load<PersonModel>();
Console.WriteLine("Load之后");
Console.WriteLine("读取名字" + pLoad.Name); Console.ReadKey();
}
输出结果如下:

留意到Get()执行的时候,就立即到数据库读取了。而Load()是延迟加载,到要用的时候,采取数据库读取,不用不读。
不用Get<>或Load<>能否缓存
下面我们把PersonDao改成这样:
public class PersonDao
{
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
ISession session; public PersonDao()
{
session = sessionFactory.OpenSession();
} public IList<PersonModel> GetPersonList()
{
return session.QueryOver<PersonModel>().List();
}
}
Program.cs
static void Main(string[] args)
{
PersonDao dao = new PersonDao();
IList<PersonModel> PersonList1 = dao.GetPersonList();
Console.WriteLine(PersonList1[].Name); IList<PersonModel> PersonList2 = dao.GetPersonList();
Console.WriteLine(PersonList1[].Name); Console.ReadKey();
}
输出:

留意到,还是执行了两次SQL语句。看来,只有Get()或Load()才能使用NHibernate的一级缓存。
三、一级缓存的管理
当我们使用Get()或Load()的时候,不想使用一级缓存怎么办呢?答案,使用
如我们回到本文的第一个示例,只改如下加粗的代码:
public class PersonDao
{
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
IStatelessSession session; public PersonDao()
{
session = sessionFactory.OpenStatelessSession();
} public PersonModel GetPersonById(int Id)
{
PersonModel p = session.Get<PersonModel>(Id);
return p;
}
}
Program.cs
static void Main(string[] args)
{
PersonDao dao = new PersonDao();
//第一次读取
PersonModel p1 = dao.GetPersonById();
Console.WriteLine(p1.Id + " " + p1.Name);
//第二次读取
PersonModel p2 = dao.GetPersonById();
Console.WriteLine(p2.Id + " " + p2.Name); Console.ReadKey();
}
输出结果如下:

可以看到NHibernate还是老老实实执行了两次SQL语句。
NHibernate提供了如下三个方法,让我们管理一级缓存。
- ISession.Evict(object):从缓存中删除指定实例。
- ISession.Clear():清空缓存。
- ISession.Contains(object):检查缓存中是否包含指定实例。
- ISession.Refresh(object):刷新缓存中的单个实例。
一个示例说明问题:
static void Main(string[] args)
{
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
ISession session = sessionFactory.OpenSession(); PersonModel p1 = session.Get<PersonModel>();
PersonModel p2 = session.Get<PersonModel>();
PersonModel p3 = new PersonModel();
Console.WriteLine(session.Contains(p1)); //输出True
Console.WriteLine(session.Contains(p2)); //输出True
session.Evict(p1); //从一级缓存中移除p1,看你还Con不Contains
Console.WriteLine(session.Contains(p1)); //输出False
Console.WriteLine(session.Contains(p2)); //输出True
session.Clear(); //全部清空,看你还Con不Containsp2
Console.WriteLine(session.Contains(p2)); //输出False Console.ReadKey();
}
输出结果如下:

刷新缓存:
static void Main(string[] args)
{
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
ISession session = sessionFactory.OpenSession(); PersonModel p1 = session.Get<PersonModel>();
Thread.Sleep();
Console.WriteLine("3秒钟之后----------------");
session.Refresh(p1); Console.ReadKey();
}
输出结果:

可以看到3秒钟之后,NHibernate重新查询了一次数据库,获得最新的对象。
NHibernate之一级缓存(第十篇)的更多相关文章
- NHibernate系列文章八:NHibernate对象一级缓存
摘要 Nhibernatea缓存非常强大,按照缓存存储在Session对象还是SessionFactory对象分为一级缓存和二级缓存. 一级缓存存在于Session对象里,也叫Session缓存,由S ...
- [Nhibernate]一级缓存
目录 写在前面 文档与系列文章 一级缓存 一个例子 一级缓存管理 总结 写在前面 上篇文章介绍了nhibernate中对象的三种状态,通过对象的三种状态,很容易想到缓存. 什麽是缓存? 有时候,某些数 ...
- NHibernate教程(19) —— 一级缓存
本节内容 引入 NHibernate一级缓存介绍 NHibernate一级缓存管理 结语 引入 大家看看上一篇了吗?对象状态.这很容易延伸到NHibernate的缓存.在项目中我们灵活的使用NHibe ...
- NHibernate二级缓存(第十一篇)
NHibernate二级缓存(第十一篇) 一.NHibernate二级缓存简介 NHibernate由ISessionFactory创建,可以被所有的ISession共享. 注意NHibernate查 ...
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
缓存的范围? 1.事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结 ...
- Python开发【第二十篇】:缓存
Python开发[第二十篇]:缓存redis&Memcache 点击这里 Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy ...
- Mybatis第八篇【一级缓存、二级缓存、与ehcache整合】
Mybatis缓存 缓存的意义 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题. myba ...
- Hibernate第七篇【对象状态、一级缓存】
前言 本博文主要讲解Hibernate的细节-->对象的状态和一级缓存- 对象状态 Hibernate中对象的状态: - 临时/瞬时状态 - 持久化状态 - 游离状态 学习Hibernate的对 ...
- 【串线篇】Mybatis缓存之一级缓存
1.体会 一级缓存:MyBatis:SqlSesion级别的缓存:默认存在,不需要设置. 机制:只要之前查询过的数据,mybatis就会保存在一个缓存中(Map):下次获取直接从缓存中拿:当前sess ...
随机推荐
- linux内核网络接收数据流程图【转】
转自:http://blog.chinaunix.net/uid-23069658-id-3141409.html 4.3 数据接收流程图 各层主要函数以及位置功能说明: 1)s ...
- Win10下Anaconda3安装CPU版本TensorFlow并使用Pycharm开发
环境:windows10 软件:Anaconda3 1.安装Anaconda 选择相应的Anaconda进行安装,下载地址点击这里,下载对应系统版本的Anaconda3. 运行 开始菜单->An ...
- 网站服务器压力Web性能测试(2):Webbench:最多模拟3万个并发连接数测试压力
1.Webbench最多可以模拟3万个并发连接数来测试服务器压力,可以设置压力测试时间和测试请求的成功率.安装Webbench命令: wget https://home.tiscali.cz/~cz2 ...
- FineReport——自定义登录页
统一的接口: http://localhost:8075/WebReport/ReportServer?op=fs_load&cmd=sso&fr_username=XX&fr ...
- leetcode 141 142. Linked List Cycle
题目描述: 不用辅助空间判断,链表中是否有环 /** * Definition for singly-linked list. * struct ListNode { * int val; * Lis ...
- 【python】msgpack使用
1.存储数据 import msgpack var={'a':'this','b':'is','c':'a test'} with open('file.name','wb') as f: msgpa ...
- centos安装更新Python2.7以及pip的安装
一.首先对相关的软件进行更新 python -V yum -y update yum groupinstall -y development yum install -y zlib zlib-dev ...
- 如何将json拼接在url后面当做地址栏参数?
function param(data) { let url = '' for (var k in data) { let value = data[k] !== undefined ? data[k ...
- 【转载】C++ typedef用法小结
http://www.cnblogs.com/charley_yang/archive/2010/12/15/1907384.html 第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替 ...
- ViewPager单页显示3个item
原文地址:https://github.com/hongyangAndroid/MagicViewPager/wiki MagicViewPager 单页显示3个Item的ViewPager炫酷切换效 ...