1. 程式人生 > 實用技巧 >NHibernate之(5):探索Insert, Update, Delete操作

NHibernate之(5):探索Insert, Update, Delete操作

本節內容

  • 操作資料概述
  • 1.新建物件
  • 2.刪除物件
  • 3.更新物件
  • 4.儲存更新物件
  • 結語

操作資料概述

我們常常所說的一個工作單元,通常是執行1個或多個操作,對這些操作要麼提交要麼放棄/回滾。想想使用LINQ to SQL,一切的東西都在記憶體中操作,只有呼叫了DataContext.SubmitChanges()方法才把這些改變的資料提交到資料庫中,LINQ to SQL那麼提交要麼回滾。

我們使用NHibernate也一樣,如果只查詢資料,不改變它的值,就不需要提交(或者回滾)到資料庫。

注意:這節,我們在上一節原始碼的基礎上,在資料訪問層中新建CRUD.cs類用於編寫操作方法,在資料訪問的測試層新建一CRUDFixture.cs類用於測試。

1.新建物件

簡單描述:新建一個物件;呼叫ISession.Save();同步ISession。

例子:在資料訪問層編寫CreateCustomer()方法,把傳過來的Customer物件儲存在資料庫中。

public int CreateCustomer(Customer customer)
{
    int newid = (int)_session.Save(customer);
    _session.Flush();
    return newid;
}

我們測試這個方法,新建一個Customer物件,呼叫CreateCustomer()方法返回新插入的CustomerId,再次根據CustomerId查詢資料庫是否存在這個物件。

[Test]
public void CreateCustomerTest()
{
    var customer = new Customer() { Firstname = "YJing", Lastname = "Lee" };
    int newIdentity = _crud.CreateCustomer(customer);
    var testCustomer = _crud.GetCustomerById(newIdentity);
    Assert.IsNotNull(testCustomer);
}

2.刪除物件

簡單描述:獲取一個物件;呼叫ISession.Delete();同步ISession。

說明:使用ISession.Delete()會把物件的狀態從資料庫中移除。當然,你的應用程式可能仍然持有一個指向它的引用。所以,最好這樣理解:Delete()的用途是把一個持久化例項變成臨時例項。 你也可以通過傳遞給Delete()一個NHibernate 查詢字串來一次性刪除很多物件。刪除物件順序沒有要求,不會引發外來鍵約束衝突。當然,有可能引發在外來鍵欄位定義的NOT NULL約束衝突。

例子:在資料訪問層編寫DeleteCustomer()方法,從資料庫中刪除Customer物件。

public void DeleteCustomer(Customer customer)
{
    _session.Delete(customer);
    _session.Flush();
}

我們測試這個方法,在資料庫中查詢CustomerId為2的Customer物件,呼叫DeleteCustomer()方法刪除,再次根據CustomerId查詢資料庫是否存在這個物件。

[Test]
public void DeleteCustomerTest()
{
    var coutomer = _crud.GetCustomerById(2);
    _crud.DeleteCustomer(coutomer);
    var testCustomer = _crud.GetCustomerById(2);
    Assert.IsNull(testCustomer);
}

3.更新物件

簡單描述:獲取一個物件;改變它的一些屬性;呼叫ISession.Update();同步ISession。

例子:在資料訪問層編寫UpdateCustomer()方法,修改Customer物件。

public void UpdateCustomer(Customer customer)
{
    _session.Update(customer);
    _session.Flush();
}

測試這個方法,在資料庫中查詢CustomerId為1的Customer物件並修改它的Firstname屬性值,呼叫UpdateCustomer()方法更新,再次查詢資料庫中CustomerId為1的Customer物件的Firstname值為修改之後的值。

[Test]
public void UpdateCustomerTest()
{
    var customer = _crud.GetCustomerById(1);
    customer.Firstname = "liyongjing";
    _crud.UpdateCustomer(customer);
    var testCustomer = _crud.GetCustomerById(1);
    Assert.AreEqual("liyongjing", customer.Firstname);
}

4.儲存更新物件

你會不會想出這個問題?哪些是剛剛建立的物件,哪些是修改過的物件?對於剛剛建立的物件我們需要儲存到資料庫中,對於修改過的物件我們需要更新到資料庫中。

幸好,ISession可以識別出這不同的物件,併為我們提供了ISession.SaveOrUpdate(object)方法

ISession.SaveOrUpdate(object)方法完成如下工作:

  • 檢查這個物件是否已經存在Session中。
  • 如果物件不在,呼叫Save(object)來儲存。
  • 如果物件存在,檢查這個物件是否改變了。
  • 如果物件改變,呼叫Update(object)來更新。

看看下面例子說明了這種情況,在資料訪問層編寫SaveOrUpdateCustomer()方法,儲存更新Customer物件列表,依次遍歷列表中的Customer物件,呼叫ISession.SaveOrUpdate(object)方法儲存更新每個Customer物件。

public void SaveOrUpdateCustomer(IList<Customer> customer)
{
    foreach (var c in customer)
    {
        _session.SaveOrUpdate(c);
    }
    _session.Flush();
}

測試這個方法,先在資料庫中查詢Firstname為YJing的Customer物件並修改它的Lastname屬性值,這些物件是資料庫中存在的,並改變了,然後新建2個Customer物件,這兩個物件在資料庫中不存在,是新建立的。呼叫SaveOrUpdateCustomer()方法儲存更新物件,即更新前面修改的物件和儲存了後面新建立的2個物件。再次查詢資料庫中Firstname為YJing,Lastname為YongJing的Customer物件是否一致了。

[Test]
public void SaveOrUpdateCustomerTest()
{
    IList<Customer> customers = _crud.GetCustomersByFirstname("YJing");
    foreach (var c in customers)
    {
        c.Lastname = "YongJing";
    }
    var c1 = new Customer() { Firstname = "YJing", Lastname = "YongJing"};
    var c2 = new Customer() { Firstname = "YJing", Lastname = "YongJing"};
    customers.Add(c1);
    customers.Add(c2);
    int initiaIListCount = customers.Count;

    _crud.SaveOrUpdateCustomer(customers);

    int testListCount = _crud.GetCustomersByFirstnameAndLastname("YJing", "YongJing").Count;
    Assert.AreEqual(initiaIListCount, testListCount);
}

結語

當然,這一節操縱物件操作,在NHibernate中涉及了物件的狀態,物件對一個特定的ISession來說,有三種狀態分別是:瞬時(transient)物件、持久化(persistent)物件、遊離(detached)物件。這一節沒有說到了,以後在討論Session的時候再介紹。

本系列連結:NHibernate之旅系列文章導航

NHibernate Q&A

下次繼續分享NHibernate!