ObjectDataSoruce 繫結 BusinessObject 控制項

ObjectDataSoruce 繫結 BusinessObject 控制項

摘要

在 ASP.NET 中,ObjectDataSoruce 控制項是實現三層式的重要關鍵,我們可以透過 ObjectDataSoruce 控制項使用的自訂中間層商務物件。不過一般找到的範例都是直接繫結中間層商務物件,雖然範例通常寫得相當符合物件導向,可是在實際運用上有下列幾個問題。

問題一:維護性不佳

例如 Employee 商務物件的 Update 方法,可能有下列二種寫法

[寫法一] Update 方法中,每個欄位皆為引數

Public Function UpdateEmployee(EmployeeID As Integer, LastName As String, FirstName As String, _
                                   Address As String, City As String, Region As String, _
                                   PostalCode As String) As Integer

參考:http://msdn.microsoft.com/zh-tw/library/ms178538(VS.80).aspx

 

[寫法二] Update 方法使用強型別,每個欄位對應到類別的屬性

Public Function UpdateEmployee(employee As NorthwindEmployee) As Integer

參考:http://msdn.microsoft.com/zh-tw/library/ms227562(VS.80).aspx

 

可是實際上真能這樣用嗎?以[方法一]為例,若異動欄位非常多,Update 方法的引數不就多到嚇死人;[方法二]使用強型別可以解決欄位多的問題,不過欄位增減時,都需要同時維護 NorthwindEmployee 類別不是很麻煩嗎?當你的系統非常龐大時,例如有上千個表單,當這些表單若需同時新增一個欄位時,那就需要同時更新上千個對應的類別,可能會搞到你瘋掉。

 

問題二:批次異動問題

當 GridView 繫結 ObjectDataSource 在編輯一筆記錄時儲存時,有時我們並不希望該筆資料馬上異動回資料庫,也就是執行 ObjectDataSoruce 的 Update 方法,但資料不要真正寫回資料庫;而是所有編輯的資料先被暫存,最後執行一個方法(例如 Save),才將這些多筆資料的異動同時寫回資料。而 ObjectDataSource 在處理這部分的問題,也很難完成。

 

問題三:Mater-Detail 問題

有些表單具 Mater-Detail 的關係(如訂單),可是 ObjectDataSource 很難描述這種關係,因為 ObjectDataSource 的角色相當於 DataTable,而 Mater-Detal 是多個 DataTable 的集合,相當於 DataSet。也就是說需要有多個 ObjectDataSource 才能描述 Master-Detal 的關係,而這些 ObjectDataSource 的異動不能馬上寫回資料庫,表單的編輯動作都需要被暫存,當按下儲存時才能將整個 DataSet 的異動同時寫回資料庫。

 

TBBusinessObject 及 TBObjectDataSource 控制項

針對以上的問題,在此使用另一種方式來處理,讓 ObjectDataSource 繫結 BusinessObject 控制項,而 BusinessObject 控制項提供 DataSet 屬性,來暫存 ObjectDataSource 產生的異動。而呼叫真正的中間層商務物件時,再將 BusinessObject 控制項的 DataSet 屬性傳入,由中間層商務物件去異動資料庫。

以下範例以 GridView 繫結 ObjectDataSource,當 GridView 進行修改、刪除的動作時,會透過 ObjectDataSource 來呼叫 BusinessObject 控制項來進行異動,而這此異動並不會被寫回資料庫,而是異動 BusinessObject 控制項的 DataSet 屬性。

一般的作法為

GridView --> ObjectDataSoruce --> 中間層 BusinessObject

而這邊的作法為

GridView --> ObjectDataSoruce --> BusinessObject 控制項 --> 中間層 BusinessObject

 

image

在頁面上放置 TBBusinessObject 控制項及 TBObjectDataSource 控制項,在 TBObjectDataSource 控制項設定 BusinessObjectID="TBBusinessObject1" 繫結至 TBBusinessObject 控制項。


            <bee:TBBusinessObject ID="TBBusinessObject1" runat="server">
            </bee:TBBusinessObject>
            <bee:TBObjectDataSource ID="TBObjectDataSource1" runat="server" 
                OldValuesParameterFormatString="original_{0}" RowIndex="-1"
                TypeName="Bee.Web.WebControls.TBBusinessObject"
                BusinessObjectID="TBBusinessObject1"
                TableName="Employee">
            </bee:TBObjectDataSource>

當 Page Load 時產生的一個 Employee 的 DataTable,並將 DataTable 加入 TBBusinessObject.DataSet.Tables。在 GridView 執行 Update 及 Delete 時,要去設定 TBObjectDataSource 的 RowIndex,使用可以異動到對應的 DataRow。


Partial Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not Me.IsPostBack Then
            Dim oTable As Data.DataTable
            Dim oColumn As Data.DataColumn
            Dim oRow As Data.DataRow

            oTable = New Data.DataTable("Employee")

            oColumn = New Data.DataColumn("ID", GetType(String))
            oTable.Columns.Add(oColumn)
            oColumn = New Data.DataColumn("Name", GetType(String))
            oTable.Columns.Add(oColumn)
            oColumn = New Data.DataColumn("Tel", GetType(String))
            oTable.Columns.Add(oColumn)

            oRow = oTable.NewRow()
            oRow("ID") = "001"
            oRow("Name") = "張三"
            oRow("Tel") = "02-11111111"
            oTable.Rows.Add(oRow)

            oRow = oTable.NewRow()
            oRow("ID") = "002"
            oRow("Name") = "李四"
            oRow("Tel") = "02-22222222"
            oTable.Rows.Add(oRow)

            oRow = oTable.NewRow()
            oRow("ID") = "003"
            oRow("Name") = "王五"
            oRow("Tel") = "02-33333333"
            oTable.Rows.Add(oRow)

            TBBusinessObject1.DataSet.Tables.Add(oTable)
            GridView1.DataBind()
        End If
    End Sub

    Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand
        Select Case e.CommandName
            Case "Update"
                TBObjectDataSource1.RowIndex = CInt(e.CommandArgument)
            Case "Delete"
                TBObjectDataSource1.RowIndex = CInt(e.CommandArgument)
        End Select
    End Sub
End Class

執行程式,GridView 會透過 TBObjectDataSource 的來取得 TBBusinessObject 中的 Employee DataTable 並顯示在 GridView 中。

image

按下編輯鈕,針對資料列進行編輯

image

按下更新鈕,異動就會被寫回 TBBusinessObject 中的 Employee DataTable。

image

當按下刪除鈕時,TBBusinessObject 中的 Employee DataTable 的該筆 DataRow 也會被刪除。

image

 

範例程式下程:BusinessObjectControl.rar

ASP.NET 魔法學院