標籤:c blog a get 檔案 使用
以下屬於不明來源資料:
引入
在程式運行過程中使用對象的方式對資料庫進行操作,這必然會產生一系列的持久化類的執行個體對象。這些對象可能是剛剛建立並準備儲存的,也可能是從資料庫中查詢的,為了區分這些對象,根據對象和當前會話的關聯狀態,我們可以把對象分為三種:
瞬時對象:對象剛剛建立。該對象在資料庫中沒有記錄,也不在ISession緩衝中。如果該對象是自動產生主鍵,則該對象的物件識別碼為空白。
持久化對象:對象已經通過NHibernate進行了持久化,資料庫中已經存在對應的記錄。如果該對象是自動產生主鍵,則該對象的物件識別碼已被賦值。
託管對象:該對象是經過NHibernate儲存過或者從資料庫中取出的,但是與之關聯的ISession已經關閉。雖然它有物件識別碼且資料庫中存在對應記錄,但是已經不再被NHibernate管理。
對象狀態
NHibernate提供了對象狀態管理的功能,支援三種對象狀態:瞬時態(Transient)、持久態(Persistent)、託管態(Detached)。
1.瞬時態(Transient)
對象剛剛建立,還沒有來及和ISession關聯的狀態。這時瞬時對象不會被持久化到資料庫中,也不會被賦上標識符。如果不使用則被GC銷毀。ISession介面可以將其轉換為持久狀態。
這像這樣,剛剛建立了一個Customer對象,是一個瞬時態對象:
var customer = new Customer() { Firstname = "zhang", Lastname = "san" };
2.持久態(Persistent)
剛被儲存的或剛從資料庫中載入的。對象僅在相關聯的ISession生命週期內有效,在資料庫中有相應記錄並有標識符。對象執行個體由NHibernate架構管理,如果有任何改動,在當然操作提交時,與資料庫同步,即將對象儲存更新到資料庫中。
3.託管態(Detached)
持久對象關聯的ISession關閉後,這個對象在ISession中脫離了關係,就是託管態了,託管對象仍然有持久對象的所有屬性,對託管對象的引用仍然有效,我們可以繼續修改它。如果把這個對象重新關聯到ISession上,則再次轉變為持久態,在託管時期的修改會被持久化到資料庫中。
對象狀態轉換
在同步資料庫的情況下執行下面的語句可以轉換對象的狀態。
測實驗證對象
ISession.Contains(object):檢查ISession中是否包含指定執行個體
重新設定ISession
private void ResetSession()
{
if (_session.IsOpen)
_session.Close();
_session = _sessionManager.GetSession();
_transaction.Session = _session;
}
1.瞬時態轉換持久態
方法一:ISession.Save():儲存指定執行個體。
[Test]
public void TransientConvertPersistentTest()
{
//瞬時態對象
var customer = new Customer() { Firstname = "zhang", Lastname = "san" };
Assert.IsFalse(_session.Contains(customer));
//仍然是瞬時態,CustomerId屬性值為空白
//關聯ISession儲存到資料庫中
_session.Save(customer);
//變為持久態,由於表中CustomerId欄位自動成長的,儲存資料庫,CustomerId欄位自動加一
//經過NHibernate類型轉換後返回CustomerId屬性值,保證資料庫與執行個體對象同步
Assert.IsTrue(_session.Contains(customer));
}
方法二:ISession.SaveOrUpdate():分配新標識儲存瞬時態對象。
2.持久態轉換託管態
方法一:ISession.Evict(object):從當前ISession中刪除指定執行個體
[Test]
public void PersistentConvertDetachedEvictTest()
{
Customer customer = _transaction.GetCustomerById(1);
Assert.IsTrue(_session.Contains(customer));
_session.Evict(customer);
Assert.IsFalse(_session.Contains(customer));
}
方法二:ISession.Close():關閉當前ISession
[Test]
public void PersistentConvertDetachedCloseTest()
{
Customer customer = _transaction.GetCustomerById(1);
Assert.IsTrue(_session.Contains(customer));
ResetSession();
Assert.IsFalse(_session.Contains(customer));
}
3.託管態轉換持久態
方法一:ISession.Update():更新指定執行個體。
[Test]
public void DetachedConvertPersistentUpdateTest()
{
Customer customer = _transaction.GetCustomerById(1);
//持久態對象
Assert.IsTrue(_session.Contains(customer));
//重新設定ISession
ResetSession();
Assert.IsFalse(_session.Contains(customer));
//託管態對象
//在託管態下可繼續被修改
customer.Firstname += "CnBlogs";
_transaction.UpdateCustomerTransaction(customer);
//轉變為持久態對象
Assert.IsTrue(_session.Contains(customer));
}
看看這個例子:在託管時期的修改會被持久化到資料庫中;
注意:NHibernate如何知道重新關聯的對象是不是“髒的(修改過的)”?如果是新的ISession,ISession就不能與對象初值來比較這個對象是不是“髒的”,我們在對應檔中定義<id>元素和<version>元素的unsaved-value屬性,NHibernate就可以自己判斷了。
[Test]
public void DetachedConvertPersistentUpdateAllTest()
{
Customer customer = _transaction.GetCustomerById(1);
//持久態對象
customer.Firstname += "zhang";
Assert.IsTrue(_session.Contains(customer));
//重新設定ISession
ResetSession();
Assert.IsFalse(_session.Contains(customer));
//託管態對象
//在託管態下可繼續被修改
customer.Firstname += "CnBlogs";
//這時一起更新
_transaction.UpdateCustomerTransaction(customer);
//轉變為持久態對象
Assert.IsTrue(_session.Contains(customer));
}
現在我們初步知道了對象的狀態。雖然對象的狀態的細節由NHibernate自己維護,但是對象狀態在NHibernate應用中還是比較重要的。同時對象狀態也涉及了NHibernate緩衝、離線查詢等內容。