[ObjectDataSource] 建立更彈性的資料來源 - ObjectDataSource 入門

如果你已經使用 ASP.NET 來進行網站設計很久了,那麼你一定很熟悉以 SqlDataSource 之類的資料來源來搭配類似 GridView, FormView, DetailsView 甚至 DropDownList 等等 Rich Control 以在網頁上展示資料。坦白說,如果你所設計的網站並不複雜,那麼你真的可以永遠藉由上述的搭配組合來達成任何你想要的功能,而無需改用 ObjectDataSource。不過,或許你的網站不會永遠那麼單純,又或許你的下一個會變得複雜,那麼你就有可能需要用到 ObjectDataSource...

 

如果你已經使用 ASP.NET 來進行網站設計很久了,那麼你一定很熟悉以 SqlDataSource 之類的資料來源來搭配類似 GridView, FormView, DetailsView 甚至 DropDownList 等等 Rich Control 以在網頁上展示資料。坦白說,如果你所設計的網站並不複雜,那麼你真的可以永遠藉由上述的搭配組合來達成任何你想要的功能,而無需改用 ObjectDataSource。

不過,或許你的網站不會永遠那麼單純,又或許你的下一個會變得複雜,那麼你就有可能需要用到 ObjectDataSource。然而,到底在什麼時候,你會開始有需要改用 ObjectDataSource 呢?

我不想提出什麼太過於具體的答案;畢竟每個人遇到的情況和習慣不一樣。但就我個人而言,我會說,等到你的資料讀取或寫入動作並不是一道 SQL 指令就能夠解決的時候,你就可能會有需要使用 ObjectDataSource。

使用 ObjectDataSource 並不是目的,而是達成另一個目的的方法。什麼另一個目的呢?就是如上所述,達成撰寫複雜資料處理的這個目的。例如,你可以在刪除一筆資料的同時,把一個 Log 寫進另一個資料庫或資料表(雖然這個動作也可以用其它做法辦到)。又例如,你可以在寫入資料庫的同時,檢查寫入的內容是否符合公司的某種 Policy。像這些動作,都不是簡單的透過 SqlDataSource 就可以達成的。

為什麼一定要使用 ObjectDataSource?沒有人規定你要還是不要使用 ObjectDataSource。但透過 ObjectDataSource,你可以很輕易的讓 ASP.NET 所提供的各式 Rich Controls 進行 DataBound 的動作,從而享受現成的使用介面,而不用從頭去寫那些複雜的控制項。

在你可以使用 ObjectDataSource 之前,你必須先著手撰寫 CRUD 程式碼。在 ASP.NET 2.0 裡面,你可以選擇自己去撰寫程式碼,或者使用 DataTable 物件。DataTable 很容易使用,可是和使用 SqlDataSource 的情況一樣,它無法應付過於複雜的情況。

 

如果你選擇自訂函數,那麼你可以從 App_Code 子目錄中新增一個類別檔案,並在裡面撰寫 Create, Read, Update 和 Delete 程序。你不一定要撰寫剛好這四個程序,視你的需要而定。例如,如果你的情況絕對不會需要把資料刪除,那麼你可以不必寫 Delete 程序(雖然會讓你的 ObjectDataSource 缺少這個功能)。你也不一定只能寫一個 Create, Read, Update 或 Delete 程序。以我自己為例,我至少會寫兩個 Read 程序,其中一個不帶參數,另一個會帶參數。不帶參數的 Read 程序(例如稱為 ReadAll())會讀取所有資料,而帶參數的 Read 程序(例如稱為 Query(ID As Integer) 或 Search(Str2Search As String))則只會讀取一個,或某一範圍的資料。

以下是讀取資料的範例程式: 

        <DataObjectMethod(DataObjectMethodType.Select)> _
        Public Function ReadAll() As DataTable

            Using conn As New SqlConnection(connStr)
                Try
                    Dim cmd As New SqlCommand("ReadAll", conn)
                    cmd.CommandType = CommandType.StoredProcedure
                    conn.Open()
                    cmd.ExecuteNonQuery()
                    Dim dt As New DataTable
                    Dim dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.Default)
                    If dr.HasRows Then
                        dt.Load(dr)
                        Return dt
                    Else
                        Return Nothing
                    End If
                Catch ex As Exception
                    Return Nothing
                End Try
            End Using
        End Function
        <DataObjectMethod(DataObjectMethodType.Select)> _
        Public Function Query(ByVal ID As Integer) As DataTable
            Using conn As New SqlConnection(connStr)
                Try
                    Dim cmd As New SqlCommand("QueryMembers", conn)
                    cmd.CommandType = CommandType.StoredProcedure
                    cmd.Parameters.Add("ID", SqlDbType.Int)
                    cmd.Parameters("ID").Value = memberId
                    conn.Open()
                    Dim dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.SingleRow)
                    Dim dt As New DataTable
                    If dr.HasRows Then
                        dt.Load(dr)
                        Return dt
                    Else
                        Return Nothing
                    End If
                Catch ex As Exception
                    Return Nothing
                End Try
            End Using
        End Function

請注意 <DataObjectMethod(DataObjectMethodType.Select)> 這一行標示。它將指示 ObjectDataSource 關於 ReadAll() 和 Query() 這兩個程序代表可用的 Select 指令(不過你必須事先 Imports System.ComponentModel 命名空間)。換句話說,當你想指定 ObjectDataSource 的 Select 指令時,VS2005 會立刻幫你把它找出來。

 

同樣的,當你在撰寫 Delete() 程序時,則可以加上 <DataObjectMethod(DataObjectMethodType.Delete)>,依此類推。

把這些指令集合寫成一個類別有個額外的好處,就是你可以以不同的角度和方式來重複使用這些程式碼。例如,我可以在這個類別中建立一個 New(ID As Integer) 程序,再建立一些 Properties,透過剛才範例中的 Query(ID) 程序去找到資料庫中某筆特定資料的值,並使得我可以在其它程式中使用類似 Dim myMember As New crudClass(CInt(txtMemberId.Text)) 的方式來建立一個 crudClass 的 Instance,並隨即以 myMember.Name, myMember.Birthday 的方式取得該筆資料的內容。又或者,你可以透過 crudClass.Delete(ID) 的方式刪除某一筆資料。

不過要注意一點:如果你在程式中建立了如上的 New(ID) 程序,你必須額外建立一個多型的不帶任何參數的 New() 程序,即使它並不做什麼事情。範例程式如下:

 

        Public Sub New()
          'Do nothing
        End Sub

如果不這麼做,你會在使用 ObjectDataSource 來做為 Rich Controls 之 DataSource 時遇到問題。

你可以利用如上所述的方法建立各種富具彈性的 ObjectDataSource。如果有需要,你以可撰寫符合不同情況的 CRUD 程序,例如專門針對資料庫中 A 類別產品撰寫它的 CRUD,對 B 類產品撰寫它的 CRUD... 最後再視需要在不同的地方建構具有不同用途的 ObjectDataSource。這裡面最大的好處,就是大量的程式碼共用 - 尤其當其中包含重要的商業邏輯的時候。


Dev 2Share @ 點部落