iT邦幫忙

DAY 17
4

OpenAccess ORM for Oracle 實戰演練系列 第 13

OpenAccess ORM for Oracle 實戰演練 Day 17

OpenAccess快速入門13
OpenAccess 快速入門將協助我們熟悉 OpenAccess,第十三篇說明如何透過 OpenAccess 刪除資料的同時,刪除關聯的資料。

PS. 老婆待產中,鐵人賽還是不能斷,在待產室中寫文貼文~~~ 老婆加油~~~ 愛你
這篇是快速入門系列的最後一篇,要說明的是如何在刪除 Master 資料時,一併將關聯的明細資料刪除。

一開始要做一點準備工作,首先,在 ProductMgmt 類別裡,把查詢一筆產品資料的程式碼重構,抽成獨立的函式:

Public Function GetProduct(ByVal Id As Long) As Products
    Dim product = (From x In cxt.Products
                          Where x.PRODUCTID = Id
                          Select x).FirstOrDefault()
    Return product
End Function

請注意,要把存取範圍設定為 Public,以利單元測試和其他專案調用。再來,我們確認一下資料庫中,目前「進擊類」的類別和所關聯的產品資料:

準備工作完成後,我們在 Model 專案中建立一個 Categories 類別,撰寫以下刪除作業所需的程式碼:

Public Class CategoriesMgmt
    Private cxt As SecondModel
    Public Sub New()
        cxt = New SecondModel()
    End Sub

    Public Function GetAttackCategories() As IList(Of Categories)
        Dim query = From x In cxt.Categories
                    Where x.CATEGORYNAME = "進擊類"
                    Select x
        Return query.ToList()
    End Function

    Public Function DeleteCategory(id As Long) As Boolean
        Dim category = GetCategory(id)
        If category Is Nothing Then
            Throw New System.NullReferenceException(String.Format("查無類別編號:{0} 的資料。", id))
        End If
        cxt.Delete(category)
        cxt.SaveChanges()
        Return True
    End Function

    Private Function GetCategory(ByVal id As Long) As Categories
        Dim category = (From x In cxt.Categories
                              Where x.CATEGORYID = id
                              Select x).FirstOrDefault()
        Return category
    End Function

End Class

和前一篇 ProductMgmt 類別的相同,主要刪除作業由 DeleteCategory() 函式處理,GetAttackCategories() 函式是之後要給頁面查詢使用的函式。現在我們加入單元測試來驗證程式是否可正確完成刪除類別及所屬產品資料的動作:

<TestMethod()> _
Public Sub DeleteCategoryTest()
    Dim target = New CategoriesMgmt()
    Dim createBo = New CreateEntities()
    Dim productBo = New ProductsMgmt()
    Dim tempProduct = createBo.CreateProductAndCategory()
    Dim expected As Boolean = True
    Dim actual = target.DeleteCategory(tempProduct.CATEGORYID)
    Assert.AreEqual(expected, actual)
    Assert.IsNull(productBo.GetProduct(tempProduct.CATEGORYID))
End Sub

單元測試失敗了!為什麼呢?看看錯誤訊息:

重點是:
ORA-01407: cannot update ("LEO"."PRODUCTS"."CATEGORYID") to NULL

這就表示,目前刪除 Categories 的資料時,OpenAccess 會把關聯的 Products 資料 CategoriesId 屬性設為 Null,但是因為這個欄位是不允許 Null,所以執行更新時會發生 Exception。

實務上,刪除 Master 資料時,對於關聯的明細資料有四種處理方式:

  1. 刪除明細資料。
  2. 把明細資料和 Master 的關聯清空。
  3. 不管明細資料。
  4. 把明細資料改和別的 Master 資料建立關聯。

上述把 CategoriesId 設定為 Null,就屬於第二種方式,不過在我們這個案例中,明顯不可行,所以我們選擇第一種方式,刪除明細資料,但該如何修改?

很簡單,請開啟 SecondModel 的視覺化設計工具,把 Products 的導覽屬性 Categories 之屬性面版打開,將【Is Dependent】設定為 True:

再執行一次單元測試,成功囉:

因為篇幅太長了,所以頁面的程式碼我就不貼了,基本上,頁面和前一篇雷同,只是同時顯示兩個 Grid,一個是類別,一個是關聯的產品,然後我們在類別的 Grid 中按刪除連結,程式調用 DeleteCategory() 函式將類別和關聯產品刪除,回到頁面上就會看到該類別和關聯的產品資料已經不見了。


上一篇
OpenAccess ORM for Oracle 實戰演練 Day 16
下一篇
OpenAccess ORM for Oracle 實戰演練 Day 18
系列文
OpenAccess ORM for Oracle 實戰演練26

1 則留言

我要留言

立即登入留言