導言
到目前為止,我們探討的教程是由表現層,業務邏輯層和數據訪問層構成的層次體系結構。數據訪問層和業務邏輯層分別在教程第一和第二章提到。在Displaying Data With the ObjectDataSource 這篇教程裡,我們探討了怎樣用ASP.NET 2.0的新控件--ObjectDataSource控件在表現層展示數據。
本教程到目前為止用這種層次結構來處理數據。然而繞過這種體系結構,通過直接把數據查詢和業務邏輯放在Web頁面上,也可以達到直接在ASP.NET頁面上訪問,插入,更新,刪除數據庫數據的目的。對十分龐大或者復雜的應用程序而言,使用層次結構對程序的成功和可維護性是很重要的。然而對很簡單的程序來說,沒有必要使用層次體系結構。
ASP.NET 2.0 提供了5個內建的數據源控件, SqlDataSource控件, AccessDataSource控件, ObjectDataSource控件, XmlDataSource控件, 和SiteMapDataSource控件。SqlDataSource控件能直接從關系型數據庫中訪問和更新數據,包括Microsoft SQL Server,Microsoft Access, Oracle, MySQL等數據庫。在本章以及接下來的3章教程裡面,我們將探討如何用SqlDataSource控件來查詢和篩選數據庫數據,包括插入,更新和刪除。
圖1:ASP.NET 2.0 的5個內建的數據源控件
比較ObjectDataSource控件和 SqlDataSource控件
從理論上說,ObjectDataSource控件和 SqlDataSource控件都是作為訪問數據的一種代理。就象在教程Displaying Data With the ObjectDataSource中討論的那樣,可以在ObjectDataSource控件中設置展示數據的數據類型,以及用來選擇,插入,更新和刪除數據所調用的方法。一旦完成了ObjectDataSource控件的設置,GridView, DetailsView, DataList等數據Web控件便可以通過綁定ObjectDataSource控件調用其Select(), Insert(), Delete(), 和 Update() methods方法。
雖然SqlDataSource控件具有和SqlDataSource控件同樣的功能,但使用SqlDataSource控件時,我們必須提供詳細的數據庫連接字符串,以及用來執行選擇,更新,插入,刪除數據的ad-hoc SQL查詢或存儲過程。當調用SqlDataSource控件的Select(), Insert(), Update(), and Delete() 方法時,SqlDataSource控件連接到數據庫,並傳遞適當的SQL查詢。下圖展示了這些方法如何連接數據庫,傳遞查詢和返回結果。
圖2 SqlDataSource控件充當訪問數據庫的代理
注意:在本章教程中我們主要關注如何從數據庫獲得數據,在後面的教程中,我們將討論如何通過設置SqlDataSource控件以支持插入,更新和刪除數據。
SqlDataSource 控件和 AccessDataSource 控件
除了 SqlDataSource 控件外,ASP.NET 2.0 還包AccessDataSource 控件。這兩種不同的控件使很多開發者誤以為AccessDataSource 控件主要是被設計來與Microsoft Access數據庫打交道,SqlDataSource 控件主要是被設計來來與Microsoft SQL Server打交道。實際情況是,SqlDataSource 控件可以與幾乎所有.NET能訪問的關系型數據庫打交道。包括任何 OleDb, ODBC,compliant data stores,比如:Microsoft SQL Server, Microsoft Access, Oracle, Informix, MySQL, and PostgreSQL等。
SqlDataSource 控件和 AccessDataSource 控件的唯一區別在於AccessDataSource 控件的數據庫連接信息只需要提供Access數據庫文件的訪問路徑。而SqlDataSource 控件則需要提供完整的連接字符串。
第一步:創建 SqlDataSource 頁面
在我們探討用SqlDataSource控件直接操作數據庫數據之前,讓我們先花些時間在我們的站點項目裡添加這些本節裡和下三節裡需要的ASP.NET頁面。首先添加一個名為SqlDataSource的文件夾,在裡面添加下列頁面,並配置為使用Site.master母板頁。
Default.aspx
Querying.aspx
ParameterizedQueries.aspx
InsertUpdateDelete.aspx
OptimisticConcurrency.aspx
圖3:為SqlDataSource相關教程添加頁面
類似在其它文件夾裡,EditInsertDelete文件夾裡的Default.aspx將列出這些教程章節。記得用戶控件提供這個功能。因此,從解決方案資源管理器中拖拽一個這個用戶控件到頁面的設計視圖,從而添加它到Default.aspx頁面
圖4:將用戶控件添加到Default.aspx頁面
最後把這4個頁面加入站點地圖中。打開Web.sitemap文件並且把下列代碼加在“Adding Custom Buttons to the DataList and Repeater”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>
圖5:更新站點地圖使之包含新的頁面
第二步:添加並設置 SqlDataSource控件
在SqlDataSource文件夾中打開Querying.aspx頁面,切換到設計試圖。從工具箱中拖一個SqlDataSource控件到設計器中,設置其ID 為 ProductsDataSource。和ObjectDataSource一樣,SqlDataSource不產生任何的聲明標記,所以現在在頁面上看起來就象一個灰色的方塊。點擊SqlDataSource控件的智能標簽,點“Configure Data Source”鏈接,進入數據源配置向導。
圖6:在智能標簽裡點擊“設置數據源”鏈接。
ObjectDataSource控件和 SqlDataSource控件的配置向導有些許不同,但最終目的都是相同的:詳細的說明了如何從數據庫獲取,插入,更新和刪除數據。ObjectDataSource控件明確指定了要訪問的數據庫,並提供了要使用的SQL查詢聲明或存儲過程的詳細情況
向導的第一步是選擇要訪問的數據庫,在下拉列表中包含了放在App_Data 文件夾中的數據庫,以及添加到服務器資源管理器的數據連接節點中的數據庫。一旦我們將一個連接到App_Data文件夾中的NORTHWIND.MDF數據庫的連接字符串添加到項目的Web.config 文件中,這個連接字符串就會出現在下拉列表的選項。如下圖,選中它,點“下一步”。
圖7:從下拉列表裡選擇NORTHWINDConnectionString
選擇數據庫後,向導轉入“如何從數據庫檢索數據”界面。有2種方式:第一種指定自定義SQL語句或存儲過程,第二種是指定來自表或視圖的列。
注意:我們先探討使用“指定來自表或視圖的列”選項的實例,稍後再探討用“自定義SQL語句或存儲過程”選項的實例。
圖8是我們點擊“指定來自表或視圖的列”單選按鈕時的畫面,這裡我們選擇Products表,返回ProductID, ProductName和UnitPrice 列。完成選擇後,在底部的方框內將顯示SQL語句: SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products]
圖8:從表Products返回數據。
完成上述設置後,點“下一步”按鈕,進入測試查詢界面,在這裡可以測試上一步所設置的查詢的結果。點擊“測試查詢”按鈕,執行查詢。
圖9:點擊“測試”,從SELECT 查詢檢索數據。
最後,點“完成”按鈕完成向導。
和ObjectDataSource一樣,SqlDataSource的向導設置只是完成了對SqlDataSource控件屬性的賦值而已,即ConnectionString 屬性和SelectCommand 屬性。完成設置之後,我們的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>部分中,連接字符串的名字。關於此語法的更多信息請參考: ASP.NET Expressions Overview
而SelectCommand屬性是SQL查詢語句或存儲過程的詳細陳述。
第三步:添加數據Web控件並綁定到SqlDataSource
一旦設置好SqlDataSource後,就可以用GridView 或DetailsView等數據Web控件綁定它。在本篇教程中我們使用GridView,從工具箱拖一個GridView控件到頁面上,在智能標簽中的“選擇數據源”裡選ProductsDataSource ,這樣就將GridView控件綁定到我們前面設置的SqlDataSource控件了。
圖10:添加GridView控件並綁定到SqlDataSource
完成綁定後,Visual Studio 會自動為GridView從數據源控件返回的每一列添加一個BoundField 或CheckBoxField 。就本文來說既然SqlDataSource從數據庫返回三列:ProductID, ProductName, 和 UnitPrice ,那麼Visual Studio就在自動在GridView中生成三列(three fields )。
花幾分鐘來設置GridView的三個BoundFields:把ProductName field的HeaderText 屬性設置為“Product Name”,UnitPrice field設置為“Price”,同時格式化為貨幣形式。修改後,你的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列出了每個產品的ProductID, ProductName, 和UnitPrice。
圖11:GridView裡列出了每個產品的ProductID, ProductName, 和UnitPrice。
測試該頁面時,GridView調用其數據源控件的Select()方法。如果我們使用ObjectDataSource控件來測試該頁面的話,它將會調用邏輯層ProductsBLL class的GetProducts() 方法。而用SqlDataSource控件的話,其Select()方法將直接鏈接到要訪問的數據庫,並傳遞SelectCommand(具體就本例而言,傳遞的是SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products])。SqlDataSource將返回的結果傳遞給GridView,後者根據從數據庫返回的每一條記錄生產一行(a row)
SqlDataSource控件及數據Web控件的內置屬性
一般來說,數據Web控件的分頁,排序,編輯,插入,刪除等屬性是由數據Web控件自身指定的,跟它所使用的數據源控件沒有太大關系。也就是說,GridView可以自由的啟用它內建的分頁,排序,編輯和刪除功能,而不管它到底是綁定到SqlDataSource控件還是ObjectDataSource控件。然而,數據Web控件的某些屬性卻要受其綁定的數據源控件及其設置的影響。
比如, 就像我們在Efficiently Paging Through Large Amounts of Data 這章教程中探討的那樣,在啟用分頁功能後,在默認情況下,每次跳轉頁面時,數據Web控件都會對所有的記錄重新檢索,盡管我們只需要顯示特定的那幾條記錄。這種模式在要檢索的數據量很大的情況下,效率會很低。不過ObjectDataSource控件可以通過自定義分頁的方法僅僅返回那些需要在當前頁面上顯示的記錄,很遺憾的是SqlDataSource控件不支持自定義分頁功能。
在默認情況下,SqlDataSource控件返回的數據可以通過GridView控件來進行分頁和排序。來做個示范,在Querying.aspx 頁面中,在GridView控件的智能標簽裡啟用分頁和排序功能,看它是否象我們期望的那樣工作。
分頁和排序的原理在於SqlDataSource控件將檢索的數據庫數據轉換成“泛型數據集”(loosely-typed DataSet)。那些被用來分頁的每條記錄就蘊含
在數據集裡面,此外,數據集支持對返回的結果進行排序。當GridView請求對數據分頁或排序時,SqlDataSource控件自動完成上述工作。
在默認情況下,SqlDataSource返回的是數據集(DataSet),你也可以使它返回一個DataReader ,方法是把它的DataSourceMode屬性設置為“DataReader”。當希望把DataReader的檢索結果轉換為現成的代碼(existing code )時,設置為DataReader往往是首選。另外DataReader比起DataSet來簡單的多,功能更強大。不過將DataSourceMode屬性設置為“DataReader”後,數據Web控件便不能啟用分頁或排序功能,因為SqlDataSource無法得知總共返回了多少條記錄,並且DataReader也不支持對返回的數據排序。
第四步:使用自定義的SQL查詢或存儲過程
前面講到,SqlDataSource控件從數據庫檢索數據的方法有2種。在第二步我們探討了從表Products返回數據的方法,現在我們探討用自定義SQL查詢的情況。
在Querying.aspx添加一個新的GridView控件,在其智能標簽的下拉列表中選擇“新建數據源”,在“選擇數據源類型”界面中選“database”,將數據源ID設置為“ProductsWithCategoryInfoDataSource”。
圖12:創建一個新的SqlDataSource控件,並命名為ProductsWithCategoryInfoDataSource
下一步,接著會詢問使用哪個數據連接,就想我們在圖7做的那樣,在下拉列表中選擇NORTHWINDConnectionString,點下一步,在配置SQL語句界面中,選擇“指定自定義SQL語句或存儲過程”,點下一步,進入“定義自定義語句或存儲過程”界面,包含“選擇”,“更新”,“刪除”,“插入”四個選項卡,在每個選項卡中,你可以在文本框中輸入自定義SQL語句,或者在下拉列表中選擇存儲過程。本章我們討論輸入自定義SQL語句,在下面的教程中再探討使用存儲過程的情況。
圖13:輸入自定義SQL語句或選擇某個存儲過程
可以手工輸入自定義SQL語句,也可以借助於查詢生成器來輔助生成。不管用哪種,都應使用如下查詢:
SELECT Products.ProductID, Products.ProductName, Categories.CategoryName FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID
圖14:使用查詢生成器圖像化的構造查詢
點下一步進入“測試查詢”界面,點“完成”結束設置。完成設置後,GridView的代碼應該看起來象下面這樣:
<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>
圖15:GridView顯示了每個產品的ID, Name和Category Name
總結:
在本章我們探討了怎樣用SqlDataSource控件查詢和顯示數據。和ObjectDataSource控件一樣,它們都是作為一種訪問數據庫的代理。我們可以在屬性窗口中或通過設置它的數據源向導,來指定它要連接的數據庫以及要執行的SQL選擇查詢(SQL SELECT query)
本文所探討的SQL選擇查詢實例從指定的查詢返回所以的記錄,實際上SqlDataSource控件還可以包含一個帶參數的WHERE字句。我們將在下一章探討帶參數的查詢。
祝編程快樂!
作者簡介
本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用 微軟Web技術。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數據教程》,希望對大家的學習ASP.NET有所幫助。