NHibernate的一級緩存,名詞好像很牛B,很難。實際上就是ISession緩存。存儲在ISession的運行週期內。而二級緩存則存儲在ISessionFactory內。sql
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對象。
看到這裏,你應該懂得注意下本身代碼的寫法了。
不想廢話,十幾行代碼說明問題:
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提供了以下三個方法,讓咱們管理一級緩存。
一個示例說明問題:
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從新查詢了一次數據庫,得到最新的對象。