天天看點

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需要從資料庫中加載資料。

NHibernate之旅(22):探索NHibernate一級緩存

執行個體2:一個會話裝載兩次持久化執行個體

[Test]
public void SessionCacheTest2()
{
    Console.WriteLine("第一次讀取持久化執行個體");
    Customer customer1 = _transaction.GetCustomerById(1);
    Console.WriteLine("第二次讀取持久化執行個體");
    Customer customer2 = _transaction.GetCustomerById(1);
    Assert.AreSame(customer1, customer2);
}      

第一次加載資料後,持久化執行個體放入緩存。第二次查詢同一個持久化執行個體時,緩存中已經存在該持久化執行個體,應用程式将直接從緩存中擷取資料,而不必再次從資料庫中讀取資料,這樣同時也提高了查詢效率,看看結果:

NHibernate之旅(22):探索NHibernate一級緩存

執行個體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));
    }
}      

在兩個會話中擷取同一持久化執行個體時,兩個會話的緩存是獨立的,一個會話的資料操作不會影響到另外一個會話。看看輸出結果:

NHibernate之旅(22):探索NHibernate一級緩存

從結果我們可以說明雖然這兩個會話讀取的是同一個執行個體,但需要兩次資料庫操作,進而證明了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);
}      

直接看結果:

NHibernate之旅(22):探索NHibernate一級緩存

測試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);
}      

看看結果:

NHibernate之旅(22):探索NHibernate一級緩存

看到不同點了嗎?這就是差別,我在測試中發現了這個秘密,使用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 Q&A

  • 歡迎加入NHibernate中文社群,一起讨論NHibernate知識!
  • 請到NHibernate中文社群下載下傳本系列相關源碼。

下次繼續分享NHibernate!