天天看點

[Nhibernate]對象狀态

目錄

寫在前面

文檔與系列文章

對象狀态

瞬時态(Transient)

持久态(Persistent)

脫管态(Detached)

對象狀态轉換

總結

前面兩篇文章介紹了SchemaExport工具的使用,使用該工具可以根據映射檔案生成資料庫架構,這篇文章将介紹nhibernate中的三種對象狀态。

在程式運作過程中,使用對象的方式操作資料庫的同時,必然會産生一系列的持久化對象。這些對象可能是剛剛建立并準備進行存儲的,也有可能是從資料庫進行查詢得到的,為了差別這些對象,根據對象和目前Session的關聯狀态,可以将對象分為三種:

瞬時對象:對象剛剛建立,該對象沒有在資料庫中進行存儲,也沒有在ISession的緩存中。如果該對象的主鍵是自動建立的,則此時對象的辨別符為空。

持久化對象:對象已經通過Nhibernate進行了持久化,資料庫中已經存在了該對象的記錄。如果該對象自動建立主鍵,則此時對象的辨別符已被指派。

托管對象:該對象已經通過NHIbernate儲存或者從資料庫中查詢取出的,但與此對象關聯的ISession已經關閉。雖然它存在對象辨別符,且在資料庫中也有對應的記錄,但已經不被Nhibernate管理的。

[Nhibernate]體系結構

[NHibernate]ISessionFactory配置

[NHibernate]持久化類(Persistent Classes)

[NHibernate]O/R Mapping基礎

[NHibernate]集合類(Collections)映射 

[NHibernate]關聯映射

[NHibernate]Parent/Child

[NHibernate]緩存(NHibernate.Caches)

[NHibernate]NHibernate.Tool.hbm2net

[NHibernate]Nullables

[NHibernate]Nhibernate如何映射sqlserver中image字段

[NHibernate]基本配置與測試 

[NHibernate]HQL查詢 

[NHibernate]條件查詢Criteria Query

[NHibernate]增删改操作

[NHibernate]事務

[NHibernate]并發控制

[NHibernate]元件之依賴對象

[NHibernate]一對多關系(級聯删除,級聯添加)

[NHibernate]一對多關系(關聯查詢)

[NHibernate]多對多關系(關聯查詢)

[NHibernate]延遲加載

[NHibernate]立即加載

[NHibernate]視圖處理

[NHibernate]N+1 Select查詢問題分析

[NHibernate]存儲過程的使用(一)

[NHibernate]存儲過程的使用(二)

[NHibernate]存儲過程的使用(三)

[Nhibernate]SchemaExport工具的使用(一)——通過映射檔案修改資料表

[Nhibernate]SchemaExport工具的使用(二)——建立表及其限制、存儲過程、視圖

NHibernate提供了對象狀态管理的功能,支援三種對象狀态:瞬時态(Transient)、持久态(Persistent)、脫管态(Detached)。

對象剛剛建立,還沒有來及和ISession關聯的狀态。這時瞬時對象不會被持久化到資料庫中,也不會被賦上辨別符。如果不使用則被GC銷毀。ISession接口可以将其轉換為持久狀态。

例如:剛剛建立一個Customer對象,就是一個瞬時态的對象。

1             //瞬時态對象
 2             var customer = new Customer()
 3             {
 4                 CustomerID = Guid.NewGuid(), 
 5                 NameAddress = new Name()
 6                 { 
 7                     CustomerAddress="北京", 
 8                     CustomerName="wolfy"
 9                 }, 
10                 Orders=null, 
11                 Version=1 
12             };      

剛被儲存的或剛從資料庫中加載的。對象僅在關聯的ISession生命周期内有效,在資料庫中有相應記錄并有辨別符。對象執行個體由NHibernate架構管理,如果有任何改動,在送出時,與資料庫同步,即将對象儲存更新到資料庫中。

持久對象關聯的ISession關閉後,這個對象在ISession中脫離了關系,就是脫管态了,托管對象仍然有持久對象的所有屬性,對托管對象的引用仍然有效的,我們可以繼續修改它。如果把這個對象重新關聯到ISession上,則再次轉變為持久态,在托管時期的修改會被持久化到資料庫中。

在同步資料庫的情況下執行下面的語句可以轉換對象的狀态。

ISession.Contains(object):檢查ISession中是否包含指定執行個體

添加一個ISession的重置方法

1         public static ISession ResetSession()
2         {
3             if (_session.IsOpen)
4                 _session.Close();
5             _session = _sessionFactory.OpenSession(); ;
6             return _session;
7         }      

瞬時态轉換為持久态

方法一:ISession.Save():儲存指定執行個體。

1         public void TransientConvertPersistent()
 2         {
 3             //瞬時态對象
 4             var customer = new Customer()
 5             {
 6                 CustomerID = Guid.NewGuid(), 
 7                 NameAddress = new Name()
 8                 { 
 9                     CustomerAddress="北京", 
10                     CustomerName="wolfy"
11                 }, 
12                 Orders=null, 
13                 Version=1 
14             };
15             ISession session = NHibernateHelper.GetSession();
16             if (!session.Contains(customer))
17             {
18                 //關聯ISession儲存到資料庫中
19                 session.Save(customer);
20             }
21             //變為持久态,由于表中CustomerId字段自動增長的(如果是自動增長主鍵),儲存資料庫,CustomerId字段自動加一
22             //經過NHibernate類型轉換後傳回CustomerId屬性值,保證資料庫與執行個體對象同步
23             if (session.Contains(customer))
24             {
25 
26             }
27         }      

方法二:ISession.SaveOrUpdate():配置設定新辨別儲存瞬時态對象。

持久态轉換為脫管态

方法一:ISession.Evict(object):從目前ISession中删除指定執行個體

1         public void PersistentConvertDetachedEvict()
 2         {
 3             //得到session
 4             ISession session = NHibernateHelper.GetSession();
 5             //根據id得到customer對象
 6             var customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));
 7             //如果包含customer對象則删除
 8             if (session.Contains(customer))
 9             {
10                 session.Evict(customer);
11             }
12         }      

方法二:ISession.Close():關閉目前ISession

1        public void PersistentConvertDetachedCloseTest()
 2         {
 3             //得到session
 4             ISession session = NHibernateHelper.GetSession();
 5             //根據id得到customer對象
 6             var customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8"));
 7             if (session.Contains(customer))
 8             {
 9                 NHibernateHelper.ResetSession();
10             }
11         }      

脫管态轉換為持久态

方法一:ISession.Update():更新指定執行個體。

1         public void DetachedConvertPersistentUpdateTest()
 2         {
 3             //得到session
 4             ISession session = NHibernateHelper.GetSession();
 5             //根據id得到customer對象
 6             Customer customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8")) as Customer;
 7             //重新設定ISession
 8             NHibernateHelper.ResetSession();
 9             //脫管态對象
10             //在脫管态下可繼續被修改
11             if (session.Contains(customer))
12             {
13                 customer.NameAddress = new Name() { CustomerAddress="上海", CustomerName="wolfy"};
14                 //轉變為持久态對象
15                 session.Update(customer);
16             }           
17         }      

通過上面的例子可以看出:在托管時期的修改會被持久化到資料庫中;

注意:NHibernate如何知道重新關聯的對象是不是“髒的(修改過的)”?如果是新的ISession,ISession就不能與對象初值來比較這個對象是不是“髒的”,我們在映射檔案中定義<id>元素和<version>元素的unsaved-value屬性,NHibernate就可以自己判斷了。

如果加上一個鎖:如果在托管時期沒有修改,就不執行更新語句,隻轉換為持久态,下面的例子如果在托管時期修改對象,執行更新語句。

1         public void DetachedConvertPersistentUpdateLockTest()
 2         {
 3             //得到session
 4             ISession session = NHibernateHelper.GetSession();
 5             //根據id得到customer對象
 6             Customer customer = session.Get("Customer", new Guid("DDF63750-3307-461B-B96A-7FF356540CB8")) as Customer;
 7             if (session.Contains(customer))
 8             {
 9                 NHibernateHelper.ResetSession();
10             }
11             //鎖
12             session.Lock(customer, NHibernate.LockMode.None);
13             //如果在托管時期沒有修改,就不執行更新語句,隻轉換為持久态
14             session.Update(customer);
15         }      

需注意Lock鎖的使用,需要保證customer對象不為null,這裡為了測試友善就沒加上判斷。如果為null會有異常(attempt to lock null)。

方法二:ISession.Merge():合并指定執行個體。不必考慮ISession狀态,ISession中存在相同辨別的持久化對象時,NHibernate便會根據使用者給出的對象狀态覆寫原有的持久化執行個體狀态。

方法三:ISession.SaveOrUpdate():配置設定新辨別儲存瞬時态對象;更新/重新關聯脫管态對象。

本篇概念性的東西比較多,對三種狀态的了解到位,就能差別三種狀态。

參考文章

http://www.cnblogs.com/lyj/archive/2008/11/17/1335181.html

  • 部落格位址:http://www.cnblogs.com/wolf-sun/

    部落格版權:如果文中有不妥或者錯誤的地方還望高手的你指出,以免誤人子弟。如果覺得本文對你有所幫助不如【推薦】一下!如果你有更好的建議,不如留言一起讨論,共同進步!

    再次感謝您耐心的讀完本篇文章。