OpenAccess快速入門10

  • 1395
  • 0
  • 2013-10-13

OpenAccess快速入門10

DotBlogs Tags: , , , , ,

OpenAccess 快速入門將協助我們熟悉 OpenAccess,第十篇來說明如何更新資料庫中的既有資料。

----------

這篇文章我們說明如何更新資料庫中,既有的產品(Product)資料。首先,我們在 Model 專案中,加入新的類別 UpdateEntities.vb,並加入以下程式碼:


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

    Public Function UpdateProduct(Id As Long) As Products
        Dim product = (From x In cxt.Products
                      Where x.PRODUCTID = Id
                      Select x).FirstOrDefault()
        If product Is Nothing Then
            Throw New System.NullReferenceException(String.Format("找不到編號:{0} 的產品資料。", Id))
        End If
        product.PRODUCTNAME = "進擊的巨人"
        product.QUANTITYPERUNIT = "50 meters"
        product.UNITPRICE = 888D
        product.UNITSONORDER = 3L
        product.UNITSINSTOCK = 9L
        product.REORDERLEVEL = 11L
        cxt.SaveChanges()

        Return product
    End Function
End Class

要更新既有資料,首先必須要找到想修改的資料,再調整資料實體物件的屬性,最後調用 SaveChanges() 函式回寫底層資料庫。上述 UpdateProduct 函式就是在做這些事情。

首先,我們透過 LINQ 取得指定編號的產品資料,這裡我們調用了 FirstOrDefault() 函式,然後如果傳入的產品編號找不到資料,我們就擲出 NullReferenceException,並設定錯誤訊息。若找的到資料,則我們就開始設定 product 實體物件的屬性值,最後調用物件容器(SecondModel)的 SaveChanges() 函式,將異動結果回寫資料庫。

同樣,我們撰寫單元測試案例來驗證上述程式碼的正確性:


<TestMethod()> _
<ExpectedException(GetType(System.NullReferenceException))> _
Public Sub UpdateProduct_RaiseException()
    Dim target As UpdateEntities = New UpdateEntities()
    Dim Id As Long = 99999999
    Dim actual As Products = target.UpdateProduct(Id)
End Sub

<TestMethod()> _
Public Sub UpdateTempProduct()
    Dim target As UpdateEntities = New UpdateEntities()
    Dim Id = CreateTempProduct()
    Dim actual As Products = target.UpdateProduct(Id)
    Assert.IsNotNull(actual.UNITPRICE)
    Assert.AreEqual(0L, actual.UNITSONORDER)
    'TODO: 測試完成,刪除剛剛新增的測試資料。
End Sub

Private Function CreateTempProduct() As Long
    Dim bo = New CreateEntities()
    Dim product = bo.CreateProductAndCategory()
    Return product.PRODUCTID
End Function

第一個測試 UpdateProduct_RaiseException() 故意傳入一個絕對不存在的產品編號給 UpdateEntities.UpdateProduct() 函式,預期會回傳一個 NullReferenceException。當然測試一定會通過,不然文章就寫不下去了咩。

第二個測試 UpdateTempProduct() 比較特別,使用和先前文章不同的測試方式,也是實務上會應用的一種做法:測試前先在資料庫中建立一筆測試用的資料,然後對此筆測試資料進行相關測試,最後測試完成後,再把此筆測試資料刪除。不過我們還沒說明如何透過 OpenAccess ORM 刪除資料,所以這裡只做了建立資料的動作。

當然,第二個測試也一定會通過,所以接下來我們回到 Web 專案,新增一個 DisplayAndUpdateProduct.aspx 頁面,放一個 GridView,並透過 LinkButton 更新選擇的產品資料:


<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="DisplayAndUpdateProduct.aspx.vb" Inherits="OpenAccessWebApp01.DisplayAndUpdateProduct" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="False">
                <Columns>
                    <asp:TemplateField HeaderText="動作">
                        <ItemTemplate>
                            <asp:LinkButton ID="btnUpdate" Text="更新資料" runat="server" CommandName="UpdateProduct" CommandArgument='<%#Eval("PRODUCTID")%>' />
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="PRODUCTID">
                        <ItemTemplate>
                            <asp:Label ID="lblProductId" Text='<%# Eval("PRODUCTID")%>' runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="PRODUCTNAME">
                        <ItemTemplate>
                            <asp:Label ID="lblProductName" Text='<%# Eval("PRODUCTNAME")%>' runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="QUANTITYPERUNIT">
                        <ItemTemplate>
                            <asp:Label ID="lblQuantityPerUnit" Text='<%# Eval("QUANTITYPERUNIT")%>' runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="UNITSINSTOCK">
                        <ItemTemplate>
                            <asp:Label ID="lblUnitsInStock" Text='<%# Eval("UNITSINSTOCK")%>' runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="UNITSONORDER">
                        <ItemTemplate>
                            <asp:Label ID="lblUnitsOnOrder" Text='<%# Eval("UNITSONORDER")%>' runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="REORDERLEVEL">
                        <ItemTemplate>
                            <asp:Label ID="lblReOrderLevel" Text='<%# Eval("REORDERLEVEL")%>' runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>

DisplayAndUpdateProduct.aspx.vb


Imports OpenAccessWebApp01Model

Public Class DisplayAndUpdateProduct
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        GridViewDataBinding()
    End Sub

    Private Sub gvProducts_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles gvProducts.RowCommand
        Dim productId As Long = 0L
        If Long.TryParse(e.CommandArgument, productId) Then
            Dim updateBo = New UpdateEntities()
            Dim product = updateBo.UpdateProduct(productId)
        End If
        GridViewDataBinding()
    End Sub

    Private Sub GridViewDataBinding()
        Dim ProductBO = New ProductsMgmt()
        gvProducts.DataSource = ProductBO.GetGiantProducts()
        gvProducts.DataBind()
    End Sub

End Class

為了讓上述程式碼可以執行,所以我們要再回到 Model 專案,新增一個 ProductMgmt 類別:


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

    Public Function GetGiantProducts() As IList(Of Products)
        Dim query = From x In cxt.Products
                    Where x.PRODUCTNAME.Contains("巨人")
                    Select x
        Return query.ToList()
    End Function
End Class

執行結果:

CC10-06-2013-4

PS. 上面這張圖是 gif 動畫,但是在 Chrome 好像不會重覆播放,所以再留個連結,才不用重整畫面:http://i.minus.com/i4QFOpoucHBQ6.Gif

--------
沒什麼特別的~
不過是一些筆記而已