NHibernate之(22):探索NHibernate一級快取
本節內容
- 引入
- NHibernate一級快取介紹
- NHibernate一級快取管理
- 結語
返回文章列表
引入
大家看看上一篇了嗎?物件狀態。這很容易延伸到NHibernate的快取。在專案中我們靈活的使用NHibernate的快取機制。NHibernate效能會大大提高的哦,我們接下來就來探索NHibernate快取機制吧,這篇我沒有準備什麼,先來學習下NHibernate一級快取。
NHibernate一級快取介紹
NHibernate一級快取即ISession快取,ISession快取屬於事務級快取,是NHibernate內建的。ISession快取中的資料只在本ISession週期內使用。
ISession例項建立後即可使用ISession快取。此後,ISession例項操作資料時,首先查詢內建快取,如果ISession快取中存在相應資料,則直接使用快取資料。如果不存在,則查詢資料庫並把其結果存在快取中。
例項1:查詢一次持久化例項
[Test] public void SessionCacheTest() { Customer customer = _transaction.GetCustomerById(1); }
我們一般就是這樣查詢一條資料,NHibernate初始化ISession後,ISession快取中不存在這個資料,這時NHibernate需要從資料庫中載入資料。
例項2:一個會話裝載兩次持久化例項
[Test] public void SessionCacheTest2() { Console.WriteLine("第一次讀取持久化例項"); Customer customer1 = _transaction.GetCustomerById(1); Console.WriteLine("第二次讀取持久化例項"); Customer customer2 = _transaction.GetCustomerById(1); Assert.AreSame(customer1, customer2); }
第一次載入資料後,持久化例項放入快取。第二次查詢同一個持久化例項時,快取中已經存在該持久化例項,應用程式將直接從快取中獲取資料,而不必再次從資料庫中讀取資料,這樣同時也提高了查詢效率,看看結果:
例項3:分別在兩個會話中裝載持久化例項
[Test] public void SessionCacheTest3() { using (_session) { Console.WriteLine("--Session 1--讀取持久化例項"); Customer customer = _transaction.GetCustomerById(1); Assert.IsTrue(_session.Contains(customer)); } ResetSession(); using (_session) { Console.WriteLine("--Session 2--讀取持久化例項"); Customer customer = _transaction.GetCustomerById(1); Assert.IsTrue(_session.Contains(customer)); } }
在兩個會話中獲取同一持久化例項時,兩個會話的快取是獨立的,一個會話的資料操作不會影響到另外一個會話。看看輸出結果:
從結果我們可以說明雖然這兩個會話讀取的是同一個例項,但需要兩次資料庫操作,從而證明了Session快取不是共享的,一個Session的快取內容只有在本Session例項範圍內可用。
例項4:比較ISession.Get()和ISession.Load()
不會吧,探索快取比較這個?呵呵,如果你理解了它們的不同,或許你對NHibernate快取還有一點了解了。開始。
測試1:使用ISession.Get()方法按識別符號獲取Customer物件,訪問識別符號,再訪問其它屬性。
[Test] public void GetExistingEntityTest() { Console.WriteLine("----獲取持久化例項----"); Customer customerGet = _session.Get<Customer>(1); Assert.IsNotNull(customerGet); Console.WriteLine("------訪問這個例項的CustomerId屬性------"); Console.WriteLine("這個例項CustomerId屬性:{0}", customerGet.CustomerId); Assert.AreEqual(customerGet.CustomerId, 1); Console.WriteLine("------訪問這個例項的FirstName屬性(不是CustomerId)-----"); Console.WriteLine("這個例項的FirstName屬性:{0}", customerGet.Name.Firstname); }
直接看結果:
測試2:使用ISession.Load()方法按識別符號獲取Customer物件,訪問識別符號,再訪問其它屬性。
[Test] public void LoadExistingEntityTest() { Console.WriteLine("----載入持久化例項----"); Customer customerLoad = _session.Load<Customer>(1); Assert.IsNotNull(customerLoad); Console.WriteLine("------訪問這個例項的CustomerId屬性----"); Console.WriteLine("這個例項CustomerId屬性:{0}", customerLoad.CustomerId); Assert.AreEqual(customerLoad.CustomerId, 1); Console.WriteLine("------訪問這個例項的FirstName屬性(不是CustomerId)----"); Console.WriteLine("這個例項的FirstName屬性:{0}", customerLoad.Name.Firstname); }
看看結果:
看到不同點了嗎?這就是區別,我在測試中發現了這個祕密,使用ISession.Get()方法立即把物件例項儲存到快取中,使用ISession.Load()方法當你需要使用的時候再訪問資料庫把這個例項儲存在快取中。
NHibernate一級快取管理
NHibernate為我們預設提供了一級快取,那麼我們想顯式地去管理ISession快取,怎麼辦呢?ISession介面為我們提供了一些方法來顯式管理一級快取。
ISession.Evict(object):從快取中刪除指定例項。
ISession.Clear():清空快取。
ISession.Contains(object):檢查快取中是否包含指定例項。
例項分析
我們寫一個測試來看看如何顯式管理吧:
[Test] public void SessionCacheManageTest() { //1.載入兩個例項放入ISession快取 Customer customer1 = _transaction.GetCustomerById(1); Customer customer2 = _transaction.GetCustomerById(2); //2.載入例項後,快取包含兩個例項 Assert.IsTrue(_session.Contains(customer1)); Assert.IsTrue(_session.Contains(customer2)); //3.從快取中刪除Customer1例項 _session.Evict(customer1); Assert.IsFalse(_session.Contains(customer1)); Assert.IsTrue(_session.Contains(customer2)); //4.清空ISession快取,例項不和快取關聯 _session.Clear(); Assert.IsFalse(_session.Contains(customer1)); Assert.IsFalse(_session.Contains(customer2)); }
首先,我們載入兩個Customer物件,先使用ISession.Evict(object)從快取中刪除一個Customer物件,再使用ISession.Clear()清空快取,使用Session.Contains(object)檢查快取中的Customer物件。
結語
關於NHibernate一級快取的內容就這些了,相信你對NHibernate一級快取有了初步的認識。接下來慢慢探索NHibernate二級快取吧。
本系列連結:NHibernate之旅系列文章導航
下次繼續分享NHibernate!
作者:李永京(YJingLee's Blog)
出處:http://lyj.cnblogs.com
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。