共用方式為


使用 SqlDataSource 控制項查詢資料 (C#)

斯科特·米切爾

下載 PDF

在先前的教學課程中,我們已使用 ObjectDataSource 控制項來完全區隔展示層和資料存取層。 從本教學課程開始,我們將著手了解如何將 SqlDataSource 控制項用於無需如此嚴格區隔展示和資料存取的簡單應用程式。

簡介

截至目前為止的所有教學課程,都會使用包含展示層、商業邏輯層和資料存取層在內的多層式架構。 數據存取層(DAL)是在第一個教學課程中製作的(建立數據存取層),而商業邏輯層是在第二個教學課程中製作的(建立商業邏輯層)。 從 使用 ObjectDataSource 顯示數據 教學課程開始,我們已瞭解如何使用 ASP.NET 2.0 的新 ObjectDataSource 控制項,以宣告式的方式與呈現層架構的介面。

儘管截至目前為止的所有教學課程都使用該架構來運用資料,但您也可以跳過該架構,直接從 ASP.NET 頁面存取、插入、更新和刪除資料庫資料。 此舉會直接將特定的資料庫查詢和商業邏輯置放在網頁中。 對規模極大或極為複雜的應用程式而言,設計、實作和使用多層式架構為成功更新和維護應用程式的重要關鍵。 不過,建立相當簡單且一次性的應用程式時,可能無需開發如此穩固的架構。

ASP.NET 2.0 提供五個內建數據源控件 SqlDataSourceAccessDataSourceObjectDataSourceXmlDataSourceSiteMapDataSource。 SqlDataSource 可用來直接存取和修改來自關聯式資料庫 (包括 Microsoft SQL Server、Microsoft Access、Oracle 和 MySQL 等) 的資料。 在本教學課程和後續的三個教學課程中,我們將著手檢視如何使用 SqlDataSource 控制項、探索如何查詢和篩選資料庫資料,以及了解如何使用 SqlDataSource 來插入、更新和刪除資料。

ASP.NET 2.0 Includes Five Built-In Data Source ControlsASP.NET 2.0 包括五個內建資料來源控件

圖 1:ASP.NET 2.0 包含五個內建資料來源控制項

比較 ObjectDataSource 和 SqlDataSource

就概念上而言,ObjectDataSource 和 SqlDataSource 控制項皆為資料的 Proxy。 如 使用 ObjectDataSource 顯示數據 教學課程中所述,ObjectDataSource 具有屬性,指出提供數據的物件類型,以及用來叫用的方法,以從基礎對象類型選取、插入、更新和刪除數據。 設定完 ObjectDataSource 屬性後,就可使用 ObjectDataSource 的 Select()Insert()Delete()Update() 方法,將 GridView、DetailsView 或 DataList 等資料 Web 控制項繫結至控制項,以便與基礎結構互動。

SqlDataSource 也具備相同的功能,但會針對關聯式資料庫 (而非物件程式庫) 運作。 使用 SqlDataSource 時,我們必須指定要執行的資料庫連接字串和臨機操作 SQL 查詢,或是已儲存的程序,以插入、更新、刪除和擷取資料。 SqlDataSource 的 Select()Insert()Update()Delete() 方法只要一經叫用,就會連接指定的資料庫,並發出適當的 SQL 查詢。 如同下方圖表所述,這些方法會負責執行連接資料庫、發出查詢和傳回結果等作業。

SqlDataSource 作為資料庫的代理

圖 2:SqlDataSource 可作為資料庫的 Proxy

注意

在本教學課程中,我們將著重探討如何從資料庫擷取資料。 在使用 SqlDataSource 控制件插入、更新和刪除資料 教學課程中,我們將瞭解如何設定 SqlDataSource 以支援插入、更新和刪除。

SqlDataSource 和 AccessDataSource 控制項

除了 SqlDataSource 控制項之外,ASP.NET 2.0 也包含 AccessDataSource 控制項。 這兩個不同的控制項,導致許多剛開始使用 ASP.NET 2.0 的開發人員不禁懷疑 AccessDataSource 控制項式專為搭配 Microsoft Access 使用所打造,而 SqlDataSource 控制項則是專為搭配 Microsoft SQL Server 使用所打造。 雖然 AccessDataSource 的設計目的是要特別使用 Microsoft Access,但 SqlDataSource 控制項可與任何 可透過 .NET 存取的關係資料庫搭配使用。 這會包括任何符合 OleDb 或 ODBC 規範的資料存放區,例如 Microsoft SQL Server、Microsoft Access、Oracle、Informix、MySQL 和 PostgreSQL 等。

AccessDataSource 和 SqlDataSource 控制項的唯一差異,在於資料庫連結資訊的指定方式。 AccessDataSource 控制項只需使用 Access 資料庫檔案的檔案路徑。 相較之下,SqlDataSource 則需使用完整的連接字串。

步驟 1:建立 SqlDataSource 網頁

在著手探索如何使用 SqlDataSource 控制項來直接使用資料庫資料之前,我們要先花點時間,為本教學課程和後續三個教學課程所使用的網站專案建立 ASP.NET 頁面。 首先要新增名為 SqlDataSource 的新資料夾。 接下來,則要將下列 ASP.NET 頁面新增至該資料夾,請務必讓每個頁面與 Site.master 主版頁面建立關聯:

  • Default.aspx
  • Querying.aspx
  • ParameterizedQueries.aspx
  • InsertUpdateDelete.aspx
  • OptimisticConcurrency.aspx

新增 SqlDataSource-Related 教學課程的 ASP.NET 頁面

圖 3:新增 SqlDataSource-Related 教學課程的 ASP.NET 頁面

如同其他資料夾一樣,Default.aspx 資料夾中的 SqlDataSource 將在所屬小節中列出教學課程。 回想一下,SectionLevelTutorialListing.ascx 使用者控制項提供了此功能。 因此,透過將此用戶控制項從「解決方案資源管理器」拖曳到頁面的設計視圖來新增至 Default.aspx

將 SectionLevelTutorialListing.ascx 使用者控件新增至 Default.aspx

圖 4:將使用者控制項新增 SectionLevelTutorialListing.ascxDefault.aspx按兩下以檢視完整大小的影像

最後,則要將這四個頁面新增為 Web.sitemap 檔案的項目。 具體來說,請在新增自訂按鈕後,將下列標記新增至 DataList 和重複項 <siteMapNode>

<siteMapNode url="~/SqlDataSource/Default.aspx"
    title="Using the SqlDataSource Control"
    description="Work directly with database data using the SqlDataSource control.">
    <siteMapNode url="~/SqlDataSource/Querying.aspx" title="Retrieving Database Data"
        description="Examines how to query data from a database that can then be
                     displayed  through a data Web control."/>
    <siteMapNode url="~/SqlDataSource/ParameterizedQueries.aspx"
        title="Parameterized Queries"
        description="Learn how to specify parameterized WHERE clauses in the
                     SqlDataSource's SELECT statement." />
    <siteMapNode url="~/SqlDataSource/InsertUpdateDelete.aspx"
        title="Inserting, Updating, and Deleting Database Data"
        description="See how to configure the SqlDataSource to include INSERT, UPDATE,
                      and DELETE statements." />
    <siteMapNode url="~/SqlDataSource/OptimisticConcurrency.aspx"
        title="Using Optimistic Concurrency"
        description="Explore how to augment the SqlDataSource to include support for
                     optimistic concurrency." />
</siteMapNode>

更新 Web.sitemap 後,請花點時間透過瀏覽器檢視教學課程網站。 現在,左側功能表會包含可編輯、插入和刪除教學課程的項目。

網站地圖現在包含 SqlDataSource 教學的項目

圖 5:網站地圖現在包含 SqlDataSource 教學的項目

步驟 2:新增和設定 SqlDataSource 控制項

首先請開啟 Querying.aspx 資料夾中的 SqlDataSource 頁面,並切換至 [設計] 檢視。 將 SqlDataSource 控制項從 [工具箱] 拖曳至 [設計工具],並將其 ID 設為 ProductsDataSource。 如同 ObjectDataSource 一樣,SqlDataSource 不會包含任何轉譯輸出,因此會於設計介面上顯示為灰色方塊。 若要設定 SqlDataSource,請按一下 SqlDataSource 智慧標籤的 [設定資料來源] 連結。

按一下 SqlDataSource 的智慧標記中的 [配置資料來源連結]

圖 6:按一下 SqlDataSource 智慧標記中的設定資料來源連結

如此就會顯示 SqlDataSource 控制項的 [設定資料來源] 精靈。 雖然精靈的步驟與 ObjectDataSource 控制項的精靈步驟有所差異,兩者的最終目標則完全相同,也就是提供詳細資料,以說明如何透過資料來源擷取、插入、更新和刪除資料。 針對 SqlDataSource,這項作業需要指定要使用的基礎資料庫,並提供臨機操作 SQL 陳述式或預存程序。

第一個精靈步驟會提示我們提供資料庫。 下拉式清單會包含在 Web 應用程式 App_Data 資料夾中找到的資料庫,以及已新增至 [伺服器總管] 中 [資料連線] 節點的資料庫。 由於我們已將 NORTHWIND.MDF 資料夾中適用於 App_Data 資料庫的連接字串新增至專案的 Web.config 檔案中,因此,下拉式清單會包含該連接字串的參考 NORTHWINDConnectionString。 從下拉式清單選擇這個項目,並按一下 [下一步]。

從 Drop-Down 清單中選擇 NORTHWINDConnectionString

圖 7:在 Drop-Down 清單中選擇NORTHWINDConnectionString

選擇資料庫後,精靈會要求傳回資料的查詢。 我們可以從資料表或檢視指定資料行,或是輸入自訂 SQL 陳述式或指定預存程序。 您可以透過 [指定自訂 SQL 陳述式或預存程序] 和 [從資料表或檢視指定資料行] 選項按鈕,以切換這個選項。

注意

針對第一個範例,我們要使用 [從資料表或檢視指定資料行] 選項。 我們將在本教學課程中的後續部分回到這個精靈,並探索 [指定自訂 SQL 陳述式或預存程序]。

圖 8 顯示選取 [從資料表或檢視指定資料行] 選項按鈕時的 [設定 Select 陳述式] 畫面。 下拉式清單會包含 Northwind 資料庫中的一組資料表和檢視,而選取的資料表或檢視則會顯示在下方的核取方塊清單中。 在這個範例中,我們要從 ProductID 資料表傳回 ProductNameUnitPriceProducts 資料行。 如同圖 8 所示,選取這些項目後,精靈會顯示所產生的 SQL 陳述式 SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products]

從 Products 表返回數據

圖 8:從表格返回數據

設定好精靈,好讓其傳回 ProductID 資料表的 ProductNameUnitPriceProducts 資料行後,請按一下 [下一步] 按鈕。 您有機會在這個最終畫面中檢查上一個步驟設定的查詢結果。 請按一下 [測試查詢] 按鈕來執行已設定的 SELECT 陳述式,並在方格中顯示結果。

按兩下 [測試查詢] 按鈕以檢閱您的 SELECT 查詢

圖 9:按兩下 [測試查詢] 按鈕以檢閱您的 SELECT 查詢

若要完成精靈,請按一下 [完成] 。

如同 ObjectDataSource 一樣,SqlDataSource 的精靈只會將值指派給控制項的屬性,也就是 ConnectionStringSelectCommand 屬性。 精靈完成後,您的 SqlDataSource 控制項宣告式標記看起來應該會如下方所示:

<asp:SqlDataSource ID="ProductsDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products]">
</asp:SqlDataSource>

ConnectionString 屬性會提供資訊來說明如何連接資料庫。 這個屬性可指派完整的硬式編碼連接字串值,或指向 Web.config 中的連接字串。 若要參考 Web.config 中的連接字串值,請使用語法 <%$ expressionPrefix:expressionValue %>expressionPrefix 通常是 ConnectionStrings,expressionValue 是 Web.config<connectionStrings>名稱。 不過,語法可用來參考資源檔案的 <appSettings> 項目或內容。 如需此語法的詳細資訊,請參閱 ASP.NET 表達式概觀

SelectCommand 屬性會指定要執行以傳回資料的臨機操作 SQL 陳述式或預存程序。

步驟 3:新增資料 Web 控制項並將其繫結至 SqlDataSource

SqlDataSource 設定完成後,即可繫結至資料 Web 控制項,例如 GridView 或 DetailsView。 在本教學課程中,我們將以 GridView 顯示資料。 將 GridView 從 [工具箱] 拖曳至頁面上,並在 GridView 智慧標籤的下拉式清單中選擇資料來源,以將其繫結至 ProductsDataSource SqlDataSource。

新增 GridView 並將它系結至 SqlDataSource 控件

圖 10:新增 GridView 並將其系結至 SqlDataSource 控件(按兩下以檢視完整大小的影像

在 GridView 智慧標籤的下拉式清單中選取 SqlDataSource 控制項後,Visual Studio 會自動針對資料來源控制項傳回的每個資料行,將 BoundField 或 CheckBoxField 新增至 GridView 中。 由於 SqlDataSource 會傳回 ProductIDProductNameUnitPrice 等三個資料行,GridView 中將有三個欄位。

請花點時間設定 GridView 的三個 BoundFields。 將 ProductName 欄位的 HeaderText 屬性變更為 [產品名稱],並將 UnitPrice 欄位變更為 [價格]。 此外,請將 UnitPrice 欄位的格式設為貨幣。 完成這些修改後,您的 GridView 宣告式標記看起來應該會如下方所示:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID"
            InsertVisible="False" ReadOnly="True" SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="Product Name"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" DataFormatString="{0:c}"
            HtmlEncode="False" />
    </Columns>
</asp:GridView>

請透過瀏覽器瀏覽此頁面。 如圖 11 所示,GridView 會列出每個產品的 ProductIDProductNameUnitPrice 值。

GridView 會顯示每個產品的 ProductID、ProductName 和 UnitPrice 值

圖 11:GridView 顯示每個產品的 ProductIDProductNameUnitPrice 值 (按下即可檢視完整大小的影像

造訪頁面時,GridView 會叫用其資料來源控制項的 Select() 方法。 使用 ObjectDataSource 控制項時,這會呼叫 ProductsBLL 類別的 GetProducts() 方法。 但使用 SqlDataSource 時,Select() 方法會建立連接指定資料庫的連線,並發出 SelectCommand (本範例中的 SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products])。 SqlDataSource 會傳回其結果,而 GridView 則會隨即列舉該結果,進而在 GridView 中為每個傳回的資料庫記錄建立資料列。

內建的資料 Web 控制項功能和 SqlDataSource 控制項

一般來說,資料 Web 控制項分頁、排序、編輯、刪除和插入等固有功能,都專屬於資料 Web 控制項,且不會與所使用的資料來源控制項相依。 這表示,GridView 可利用內建的分頁、排序、編輯和刪除,無論該功能是否繫結至 ObjectDataSource 或 SqlDataSource。 不過,特定資料 Web 控制項功能則對所使用的資料來源控制項或資料來源控制項的設定相當敏感。

例如,在 高效地處理大量數據的分頁 教學課程中,我們討論了資料網頁控制項的分頁邏輯預設會從基礎數據源返回 所有 記錄,然後根據目前頁面索引和每頁顯示的記錄數量僅顯示合適的記錄子集。 逐頁瀏覽大量的結果集時,這個模型會顯得相當沒有效率。 幸運的是,ObjectDataSource 可設定為支援自訂分頁,如此就能只傳回要顯示的確切記錄子集。 然而,SqlDataSource 控制項則缺少實作自訂分頁的相關屬性。

SqlDataSource 在分頁和排序上還存在另一個微妙的差異。 根據預設,從 SqlDataSource 傳回的資料可透過 GridView 進行分頁或排序。 為了加以示範,請在 Querying.aspx 中核取 GridView 智慧標籤的 [啟用分頁] 和 [啟用排序] 選項,並確認是否如預期般運作。

排序和分頁可正常運作,因為 SqlDataSource 會將資料庫資料擷取至類型鬆散的 DataSet。 您可以從 DataSet 確認實作分頁的重要層面之一,也就是查詢所能傳回的記錄總數。 此外,DataSet 的結果也能透過 DataView 排序。 GridView 要求分頁或排序資料時,SqlDataSource 將自動使用這些功能。

您可以將 SqlDataSource 設定為將 DataReader 取代 DataSet,方法是將其 DataSourceMode 屬性DataSet (預設值) 變更為 DataReader。 如果要將 SqlDataSource 的結果傳遞至預期收到 DataReader 的現有程式碼,最好使用 DataReader。 此外,由於 DataReader 是比 DataSet 更加簡單的物件,它們可提供更出色的效能。 然而,如果進行這項變更,資料 Web 控制項將無法進行排序或分頁,原因在於:SqlDataSource 無法確認查詢會傳回多少筆記錄,DataReader 也無法提供任何可排序已傳回資料的技術。

步驟 4:使用自訂的 SQL 陳述式或預存程序

設定 SqlDataSource 控制項時,可在兩個方法之間擇一,將用來傳回資料的查詢指定為自訂 SQL 陳述式或預存程序,或指定為現有資料表或檢視中的資料行。 我們已在步驟 2 中了解如何從 Products 資料表選取資料行。 現在,讓我們看看如何使用自訂 SQL 陳述式。

請將另一個 GridView 控制項新增至 Querying.aspx 頁面,並在智慧標籤的下拉式清單中選擇建立新的資料來源。 接著,請指出資料將從資料庫提取,如此就會建立新的 SqlDataSource 控制項。 請為控制項 ProductsWithCategoryInfoDataSource 命名。

建立名為 ProductsWithCategoryInfoDataSource 的新 SqlDataSource 控件

圖 12:建立名為 ProductsWithCategoryInfoDataSource 的新 SqlDataSource 控制項

下一個畫面會要求我們指定資料庫。 請比照圖 7,在下拉式清單中選擇 NORTHWINDConnectionString,並按一下 [下一步]。 在 [設定 Select 陳述式] 畫面中,選擇 [指定自訂 SQL 陳述式或預存程序] 選項按鈕,並按一下 [下一步]。 這將顯示 [定義自訂陳述式或預存程序] 畫面,當中會提供標示為 SELECT、UPDATE、INSERT 和 DELETE 的索引標籤。 在每個索引標籤中,您可以將自訂 SQL 陳述式輸入至文字方塊內,或從下拉式清單選擇預存程序。 在本教學課程中,我們將探討如何輸入自訂 SQL 陳述式;下一個教學課程則涵蓋使用預存程序的範例。

輸入自定義 SQL 語句或挑選預存程式

圖 13:輸入自訂 SQL 語句或挑選預存程式

自訂 SQL 陳述式可手動輸入至文字方塊中,或透過按一下 [查詢產生器] 按鈕來透過圖形化方式建構。 在 [查詢產生器] 或文字方塊中,使用下列查詢來傳回 ProductID 資料表中的 ProductNameProducts 欄位,藉此使用 JOINCategoryName 資料表擷取產品的 Categories

SELECT Products.ProductID, Products.ProductName, Categories.CategoryName
FROM Categories
    INNER JOIN Products ON
        Categories.CategoryID = Products.CategoryID

您可以使用查詢產生器以圖形方式建構查詢

圖 14:您可以使用查詢產生器以圖形方式建構查詢

指定查詢後,請按一下 [下一步],以繼續前往 [測試查詢] 畫面。 請按一下 [結束],以完成 SqlDataSource 精靈。

完成精靈後,GridView 將新增三個 BoundField,以顯示從查詢傳回的 ProductIDProductNameCategoryName 資料行,並產生下列宣告式標記:

<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ProductsWithCategoryInfoDataSource"
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID"
            InsertVisible="False" ReadOnly="True" SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="ProductName"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
            SortExpression="CategoryName" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="ProductsWithCategoryInfoDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="
        SELECT Products.ProductID, Products.ProductName, Categories.CategoryName
        FROM Categories
        INNER JOIN Products ON Categories.CategoryID = Products.CategoryID">
</asp:SqlDataSource>

GridView 會顯示每個產品的標識碼、名稱和相關聯的類別名稱

圖 15:GridView 顯示每個產品的識別碼、名稱和相關聯的類別名稱(按兩下即可檢視完整大小的影像

摘要

在本教學課程中,我們已了解如何使用 SqlDataSource 控制項來查詢和顯示資料。 如同 ObjectDataSource 一樣,SqlDataSource 也可做為 Proxy,以提供存取資料的宣告式方法。 其屬性會指定要連接的資料庫,以及要執行的 SQL SELECT 查詢;它們可透過 [屬性] 視窗指定,或使用 [設定 DataSource] 精靈指定。

本教學課程中的 SELECT 查詢範例會傳回指定查詢中的所有記錄。 然而,SqlDataSource 控制項則可包括 WHERE 子句,而其參數值能透過程式設計方式指派,或從指定來源自動提取。 在下一個教學課程中,我們將著手了解如何建立和使用參數化查詢!

祝您程式設計愉快!

深入閱讀

如需深入了解本教學課程中探討的多個主題,請參閱下列資源:

關於作者

斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 Scott 擔任獨立顧問、講師和作家。 他的最新書是在24小時內自學ASP.NET 2.0。 可以透過 mitchell@4GuysFromRolla.com 聯絡他。

特別感謝

本教學課程系列已經過許多熱心的檢閱者檢閱。 本教學的主要審閱者是 Susan Connery、Bernadette Leigh 和 David Suru。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請在 mitchell@4GuysFromRolla.com給我留言。