• 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(3);
                Console.WriteLine(p1.Id + " " + p1.Name);
                //第二次读取
                PersonModel p2 = dao.GetPersonById(3);
                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>(1);
                Console.WriteLine("Get之后");
                Console.WriteLine("读取名字" + pGet.Name);
                Console.WriteLine("=====================================");
                Console.WriteLine("Load之前");
                PersonModel pLoad = session.Load<PersonModel>(2);
                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[0].Name);
    
                IList<PersonModel> PersonList2 = dao.GetPersonList();
                Console.WriteLine(PersonList1[0].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(3);
                Console.WriteLine(p1.Id + " " + p1.Name);
                //第二次读取
                PersonModel p2 = dao.GetPersonById(3);
                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>(1);
                PersonModel p2 = session.Get<PersonModel>(2);
                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>(1);
                Thread.Sleep(3000);
                Console.WriteLine("3秒钟之后----------------");
                session.Refresh(p1);
    
                Console.ReadKey();
            }

      输出结果:

      

      可以看到3秒钟之后,NHibernate重新查询了一次数据库,获得最新的对象。

  • 相关阅读:
    GeoServer源码解析和扩展 (三)结构篇
    GeoServer源码解析和扩展 (一)基础篇
    开放GIS标准OGC之路(4)之 解密Filter
    开放GIS标准OGC之路(3)之 WFS初探
    养成重构的习惯有多重要
    使用GeoTools遇到的两个小问题:nvarchar类型字段无法识别,主键字段无法识别
    OGC之路(1) 之 WMS标准学习总结
    移动端flex布局
    推一把随机回帖模块
    用htmlparser来获取你想要的内容
  • 原文地址:https://www.cnblogs.com/kissdodog/p/3315669.html
Copyright © 2020-2023  润新知