ASP.NET 2.0數據教程:創建數據訪問層
創建一個數據訪問層
與數據打交道時,一種做法是把跟數據相關的邏輯直接放在表現層中(在一個web應用里,asp.net網頁構成了表現層)。其形式一般是在asp.net 網頁的編碼部分寫ADO.NET 編碼或者在標識符部分使用SqlDataSource控件。在這兩種形式里,這種做法都把數據訪問邏輯與表現層緊密耦合起來了。但推薦 的做法是,把數據訪問邏輯從表現層分離開來。這個分開的層被稱作是數據訪問層,簡寫為DAL,一般是通過一個單獨的類庫項目來實現的。這種分層框架的好處在很多文獻里都有闡述(詳見本教程***的“附加讀物”里的資源),在本系列中我們將采用這種方法。
跟底層數據源相關的所有編碼,譬如建立到數據庫的連接,發出SELECT,INSERT ,UPDATE,和DELETE命令等的編碼,都應該放置在DAL中。表現層不應該包含對 這些數據訪問編碼的任何引用,而應該調用DAL中的編碼來作所有的數據訪問請求。數據訪問層包含訪問底層數據庫數據的方法。譬如,Northwind數據庫中,有Products和Categories兩個表,它們記錄了可供銷售的產品以及這些產品所屬的分類。在我們的DAL中,我們將有下面這樣的方法:
GetCategories(), 返回所有分類的信息
GetProducts(), 返回所有產品的信息
GetProductsByCategoryID(categoryID), 返回屬于指定分類的所有產品的信 息
GetProductByProductID(productID), 返回指定產品的信息
這些方法,被調用后,將連接到數據庫,發出合適的查詢,然后返回結果。我們如何返回這些結果是很重要的。這些方法可以直接返回數據庫查詢填充的DataSet 或者DataReader ,但理想的辦法是把這些結果以強類型對象的形式返回。一個強類型的對象,其schema是編譯時嚴格定義好的,而相比之下,弱類型的對象,其schema在運行時之前是未知的。
譬如,DataReader和普通的DataSet是弱類型對象,因為它們的schema是被用來填充它們的數據庫查詢返回的字段來定義的。要訪問弱類型DataTable中的一個特定字段,我們需要用這樣的句法:DataTable.Rows[index] ["columnName"]。這個例子中的DataTable的弱類型性質表現在于,我們需要通過一個字符串或序號索引來訪問字段名稱。而在另一個方面,一個強類型的DataTable,它的所有的字段都是通過屬性的形式來實現的,訪問的編碼就會象這樣:DataTable.Rows[index].columnName。
要返回強類型對象,開發人員可以創建自定義業務對象,或者使用強類型的DataSet。開發人員實現的業務對象類,其屬性往往是對相應的底層數據表的字段的映射。而一個強類型的DataSet,則是Visual Studio基于數 據庫schema為你生成的一個類,其成員的類型都是由這個schema決定的。強類型的DataSet本身,是由繼承 于ADO.NET中DataSet,DataTable,和DataRow類的子類組成的。除了強類型的DataTable外,強類型的DataSet現在還包括TableAdapter類,這些類包含了填充DataSet中的DataTable和把 DataTable的改動傳回數據庫的各種方法。
注意:想了解使用強類型DataSet比之業務對象的優缺點的更多信息,請參考設計數據層組件以及在層間傳輸數據一文。
在這些教程的架構里,我們將使用強類型的DataSet。圖3示范說明了使用強類型的DataSet之應用程序的不同層間的流程(workflow)。
圖 3: 把所有的數據訪問編碼委托給DAL
創建數據訪問層:創建強類型的DataSet和Table Adapter
我們開始創建我們的DAL,先給我們的項目添加一個強類型的DataSet。做法如下,在解決方案管理器里的項目節點上按右鼠標,選擇“添加新項(Add a New Item)”。在模板列單里選擇DataSet,將其命名為Northwind.xsd。
圖 4: 給你的項目添加一個新的DataSet
在點擊“添加(Add)”按鈕后,Visual Studio會問我們是否將DataSet添加到App_Code文件夾中,選擇“Yes” 。然后Visual Studio會顯示強類型的DataSet的設計器,同時會啟動TableAdapter配置向導,允許你給你的強 類型DataSet添加***個TableAdapter。
強類型的DataSet 起了強類型對象的集合的作用,它由強類型DataTable實例組成,每個強類型DataTable又進 而由強類型的DataRow實例組成。我們將為這個教程系列要用到的每個數據表建立一個對應的強類型DataTable 。讓我們開始吧,先為Products表建立一個DataTable。
記住,強類型的DataTable并不包括如何訪問對應底層的數據表的任何信息。要獲取用來填充DataTable的數據 ,我們使用TableAdapter類,它提供了數據訪問層的功能。對于我們的Products DataTable,相應的TableAdapter 類將包 括GetProducts()和GetProductByCategoryID(categoryID)等方法,而我們將在表現層調用這些方法。DataTable的作用是在分層間傳輸數據。
TableAdapter配置向導首先要你選擇使用哪個數據庫。下拉框里列出了服務器資源管理器內的那些數據庫。如果你預先沒有把Northwind數據庫添加到服務器資源管理器里去的話,這時你可以點擊新連接按鈕來添加。
圖 5: 在下拉框里選擇Northwind數據庫
選擇好數據庫后,按“下一步”按鈕,向導會問你是否想在Web.config文件里存放連接字符串。將連接字符串存放在Web.config文件里,你可以避免把連接字符串硬寫在TableAdapter類的編碼中,如果將來連接字符串信息改動的話,這種做法會極大地簡化要做的編碼改動。如果你選擇在配置文件存 放連接字符串,連接字符串將被置放于段落中,這個段落可以被加密來提高安全,也可以通過IIS 圖形界面管理工具中的新的asp.net 2.0屬性頁來修改。當然這個工具更適于管理員。
圖6: 在Web.config中存放連接字符串
創建數據訪問層的下一步,我們需要定義***個強類型的DataTable的schema,同時為用來填充強類型DataSet的TableAdapter類提供***個方法。這兩步可以通過建立一個返回對應于DataTable的數據表的字段的查詢同時完成。在向導的***,我們將為這個查詢對應的方法命名。完成后,這個方法可以在表現層調用,它會執行設置好的查詢,進而填充一個強類型的DataTable。
開始定義SQL查詢之前,我們必須首先選擇我們想要TableAdapter執行查詢的方式。我們可以直接用ad-hoc的SQL語句,或建立一個新的存儲過程,或使用現存的存儲過程。在這些教程里,我們將使用ad-hoc的SQL語句。請參考Brian Noyes的文章“使用Visual Studio 2005 DataSet 設計器創建數據訪問層”中使用存儲過程的例子。
圖 7: 用SQL語句查詢數據
至此,我們可以手工輸入SQL查詢。當生成TableAdapter的***個方法時,你一般想要讓你的查詢返回那些需要在對應的DataTable中存放的字段。我們可以建立一個從Products表里返回所有字段,所有數據行的查詢來達到我們的目的:
圖 8: 在文本框里輸入SQL查詢
或者,我們可以使用查詢生成器(Query Builder),用圖形界面來構造查詢,如圖9所示。
圖 9: 通過查詢編輯器生成查詢
在生成查詢之后,在移到下一屏之前,點擊“高級選項(Advanced Options)”按鈕。在網站項目里,在默認 情形下,“生成插入,更新,刪除語句”是唯一已被選中的選項。如果你在類庫項目或Windows項目里運行這個向導的話,“采用優化的并發控制(optimistic concurrency)”選項也會被選中。現在先別選“采用優化的并發 控制”這個選項。在以后的教程里我們會詳細討論優化的并發控制。
圖 10: 只選“生成插入,更新和刪除語句”這個選項
在核實高級選項后,按“下一步(Next)”按鈕轉到***一屏。在這里,配置向導會問我們要給TableAdapter選擇添加什么方法。填充數據有兩種模式:
填充DataTable – 這個做法會生成一個方法,該方法接受一個DataTable的參數,基于查詢的結果填充這個DataTable。譬如,ADO.NET的DataAdapter類就是在它的Fill()方法中實現這個模式的 。
返回DataTable – 這個做法會生成一個方法,該方法會創建并填充一個DataTable,然后將 其作為方法的返回值。
你可以讓TableAdapter實現其中一個模式或者同時實現兩個模式。你也可以重新命名這里提供的這些方法。讓 我們對兩個復選框的選項不做改動,雖然我們在這些教程里只需要使用后面這個模式。同時,讓我們把那個很 一般性的GetData方法名改成GetProducts。
這***一個復選框,“生成DB直接方法(GenerateDBDirectMethods)”,如果選了的話,會為TableAdapter自動生 成Insert(),Update(),和Delete()方法。如果你不選這個選項的話,所有的更新都需要通過TableAdapter唯一的Update()方法來實現,該方法接受一個強類型的DataSet,或者一個DataTable,或者單個DataRow,或者一個DataRow數組。(假如你 在圖9所示的高級屬性里把“生成添加,更新和刪除語句”的選項去掉的話,這個復選框是不起作用的)。讓我們保留這個復選框的選項。
圖 11: 把方法名字從 GetData 改成 GetProducts
按“完成”按鈕結束向導。在向導關閉后,我們回到DataSet設計器中,它會顯示我們剛創建的DataTable。你可以看到Products DataTable的字段列單(ProductID, ProductName 等),還有ProductsTableAdapter的Fill()和GetProducts()方法 。
圖 12: Products DataTable和ProductsTableAdapter被添加到強類型DataSet中
至此,我們生成了含有單一DataTable類(Northwind.Products)的強類型DataSet以及一個含 有GetProducts()方法的強類 型DataAdapter類(NorthwindTableAdapters.ProductsTableAdapter)。通過這些對象可以用下 列編碼來獲取所有產品的列單:
- NorthwindTableAdapters.ProductsTableAdapter
- productsAdapter = new
- NorthwindTableAdapters.ProductsTableAdapter();
- Northwind.ProductsDataTable products;
- products = productsAdapter.GetProducts();
- foreach (Northwind.ProductsRow productRow in products)
- Response.Write("Product: " +
- productRow.ProductName + "");
這段編碼不要求我們寫一行的跟數據訪問有關的編碼。我們不需要生成任何ADO.NET類的實例,我們不需要 指明任何連接字符串,任何SQL查詢語句,或者任何存儲過程。TableAdapter為我們提供了底層的數據訪問編 碼!
這個例子里的每個對象都是強類型的,允許Visual Studio提供IntelliSense幫助以及編譯時類型檢查。最棒 的是,從TableAdapter 返回的DataTable可以直接綁定到asp.net數據Web 控件上去,這樣的控件包 括GridView,DetailsView,DropDownList,CheckBoxList,以及另外幾個控件。下面這個例子示范只要 在Page_Load事件處理函數里添加短短的三行編碼就能將從GetProducts()方法返 回的DataTable綁定到一個GridView上去。
AllProducts.aspx
asp.net
- < %@ Page Language="C#"
- AutoEventWireup="true" CodeFile="AllProducts.aspx.cs"
- Inherits="AllProducts" %>
- < !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
- Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- < html xmlns="http://www.w3.org/1999/xhtml" >
- < head runat="server">
- < title>View All Products in a GridViewtitle>
- < link href="Styles.css"
- rel="stylesheet"
- type="text/css"
- />
- head>
- < body>
- < form id="form1" runat="server">
- < div>
- < h1>
- All Productsh1>
- < p>
- < asp:GridView ID="GridView1" runat="server"
- CssClass="DataWebControlStyle">
- < HeaderStyle CssClass="HeaderStyle" />
- < AlternatingRowStyle CssClass="AlternatingRowStyle" />
- asp:GridView>
- p>
- div>
- form>
- body>
- html>
AllProducts.aspx.cs
- using System;
- using System.Data;
- using System.Configuration;
- using System.Collections;
- using System.Web;
- using System.Web.Security;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using System.Web.UI.WebControls.WebParts;
- using System.Web.UI.HtmlControls;
- using NorthwindTableAdapters;
- public partial class
- AllProducts : System.Web.UI.Page
- {
- protected void
- Page_Load(object sender, EventArgs e)
- {
- ProductsTableAdapter productsAdapter = new
- ProductsTableAdapter();
- GridView1.DataSource = productsAdapter.GetProducts();
- GridView1.DataBind();
- }
- }
圖 13: 顯示在GridView里的產品列單
這個例子要求我們在asp.net網頁的Page_Load事件處理函數里,寫三行編碼。在以后的教程里,我們將討論使用ObjectDataSource,用聲明的方式來從DAL中獲取數據。用ObjectDataSource的話,我們一行編碼都不用寫,而且還能得到分頁和排序支持呢!
【編輯推薦】
- 如何在IIS6.0中部署asp.net mvc程序
- 用Winform傻瓜式搭建asp.net mvc框架
- ASP.NET Session失效的編程思路
- ASP.NET Session 狀態的存儲
- 了解ASP.NET Web應用程序模型




























