NHibernate之一級緩存(第十篇)

  NHibernate的一級緩存,名詞好像很牛B,很難。實際上就是ISession緩存。存儲在ISession的運行週期內。而二級緩存則存儲在ISessionFactory內。sql

1、ISession一級緩存測試

  ISession默認開啓一級緩存,不須要任何配置。ISession緩存在ISession建立後就可使用,之後每次經過此ISession操做數據時,ISession會檢測自身是否緩存有相應的數據,若是有則直接返回。若是沒有,這時才查詢數據庫返回,同時緩存到ISession。當釋放ISession實例的時候,緩存自動銷燬。數據庫

  示例:緩存

  首先咱們先開啓配置文件中的show_sql節點:session

  <property name="show_sql">true</property>  //開啓這個對本緩存測試沒影響,只是看看效果

  PersonDao.csless

    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();
        }
    }

  輸出:ui

  

  咱們看到只有第一次查詢執行了SQL語句,第二次並無執行任何語句。這點從SQL Server Profiler中也可監控到。spa

  

  在兩個會話中得到同一實例code

  下面咱們把對象

    sessionFactory.OpenSession();

  這行代碼放到方法裏面會怎麼樣呢?

        public PersonModel GetPersonById(int Id)
        {
            ISession session = sessionFactory.OpenSession();
            PersonModel p = session.Get<PersonModel>(Id);
            return p;
        }

  輸出結果以下:

  

  留意到每OpenSession一次,緩存就沒有了。OpenSession一次,NHibernate會自動釋放原有的ISession對象。

  看到這裏,你應該懂得注意下本身代碼的寫法了。

2、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的一級緩存。

3、一級緩存的管理

  當咱們使用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從新查詢了一次數據庫,得到最新的對象。

相關文章
相關標籤/搜索