ASP.NET2.0+SQL Server2005构建多层应用 [转]
隨著.net 2.0的發(fā)布,將會(huì)使得使用ASP.NET 2.0來(lái)構(gòu)建的Web應(yīng)用越來(lái)越容易。使用ASP.NET 2.0和SQL Server 2005,將會(huì)比ASP.NET 1.1更方便地構(gòu)建多層體系架構(gòu)的web應(yīng)用。本文,將使用ASP.NET 2.0和SQL Server 2005 (.net使用Visual Studio 2005 beta 2,SQL Server 2005使用april ctp版本)來(lái)構(gòu)建一個(gè)簡(jiǎn)單的多層應(yīng)用的例子,并且說(shuō)明其中在.NET 2.0和SQL Server 2005中的一些新的特性,比如objectdatasource,master pages,clr 存儲(chǔ)過(guò)程,tableadapter向?qū)У取?/p>
多層應(yīng)用簡(jiǎn)介
什么是多層架構(gòu)的應(yīng)用呢?傳統(tǒng)上的CLR模式便是兩層應(yīng)用的典型例子,也就是客戶機(jī)/服務(wù)器模式。這種模式只是兩層架構(gòu),客戶機(jī)發(fā)出請(qǐng)求給服務(wù)器,服務(wù)器將處理大量來(lái)自客戶端的請(qǐng)求,經(jīng)過(guò)業(yè)務(wù)邏輯運(yùn)算和處理后,再返回給客戶端。兩層架構(gòu)的模式顯然不能滿足現(xiàn)代以互聯(lián)網(wǎng)為趨勢(shì)的企業(yè)計(jì)算處理要求,因?yàn)槠洳渴?#xff0c;負(fù)載均衡等處理十分麻煩,所以就有了三層架構(gòu)乃至于多層架構(gòu)便出現(xiàn)了。多層架構(gòu)的核心思想是,將整個(gè)業(yè)務(wù)應(yīng)用劃分為表示層-業(yè)務(wù)層―數(shù)據(jù)訪問(wèn)層-數(shù)據(jù)庫(kù),明確地將客戶端的表示層、業(yè)務(wù)邏輯訪問(wèn)、和數(shù)據(jù)訪問(wèn)及數(shù)據(jù)庫(kù)訪問(wèn)劃分出來(lái),十分有利于系統(tǒng)的開(kāi)發(fā),維護(hù)、部署和擴(kuò)展。下面我們以典型的一個(gè)例子來(lái)說(shuō)明,如何使用ASP.NET 2.0和SQL Server 2005來(lái)構(gòu)建一個(gè)多層應(yīng)用。
我們的這個(gè)例子十分簡(jiǎn)單,但足以能夠說(shuō)明問(wèn)題。我們的應(yīng)用只有兩個(gè)頁(yè)面,第一個(gè)頁(yè)面將調(diào)用SQL Server 2005數(shù)據(jù)庫(kù)中的pubs數(shù)據(jù)庫(kù)的author表,列出所有的作者,然后點(diǎn)選每個(gè)作者的鏈接,將顯示該作者寫(xiě)過(guò)哪些書(shū)籍。
下面的圖,說(shuō)明了在ASP.NET 2.0架構(gòu)下,我們的這個(gè)多層應(yīng)用的架構(gòu)圖:?
從上圖可以看出,我們將以這樣的方式來(lái)構(gòu)建這個(gè)多層應(yīng)用。首先,從圖的最上方開(kāi)始看,藍(lán)色部分的是表示層,就是我們web應(yīng)用的外觀顯示,該層直接和用戶打交道,比如處理輸入輸出等,在ASP.NET 2.0中,我們可以使用master page模版技術(shù),以構(gòu)建一個(gè)外觀風(fēng)格保持一致的頁(yè)面(這在下文中會(huì)提到)。接下來(lái)是業(yè)務(wù)邏輯層,一般在該層中會(huì)直接處理業(yè)務(wù)邏輯及相關(guān)計(jì)算等,而在ASP.NET 2.0中,我們可以很方便地通過(guò)使用objectdatasource控件來(lái)處理業(yè)務(wù)邏輯層。
業(yè)務(wù)邏輯層再接著和數(shù)據(jù)訪問(wèn)層(data Access layer)打交道。數(shù)據(jù)訪問(wèn)層的作用是,將所有對(duì)數(shù)據(jù)庫(kù)操作的有關(guān)過(guò)程業(yè)務(wù)分離出來(lái),當(dāng)數(shù)據(jù)庫(kù)的結(jié)構(gòu)等發(fā)生改變時(shí),只需要對(duì)數(shù)據(jù)訪問(wèn)層的代碼進(jìn)行修改就可以了,不需要再修改其他的地方,這樣會(huì)方便和不同的數(shù)據(jù)庫(kù)進(jìn)行打交道。在ASP.NET 2.0中,通過(guò)使用TableAdapter數(shù)據(jù)向?qū)Р僮?#xff0c;可以十分快速地從已有的數(shù)據(jù)庫(kù)中,生成數(shù)據(jù)訪問(wèn)層的代碼,而基本上不需要寫(xiě)什么代碼。
最后,我們通過(guò)使用SQL Server 2005 新特性:clr stored procedure(clr 存儲(chǔ)過(guò)程),來(lái)創(chuàng)建存儲(chǔ)過(guò)程。在SQL Server 2005 中,你可以使用自己熟悉的.NET語(yǔ)言來(lái)創(chuàng)建存儲(chǔ)過(guò)程了。
使用SQL Server 2005 的CLR存儲(chǔ)過(guò)程
SQL Server 2005的一大新特性便是整合了.net 的CLR。整合了.net CLR的好處在于,可以很方便地使開(kāi)發(fā)者可以使用自己熟悉的.net 語(yǔ)言來(lái)創(chuàng)建存儲(chǔ)過(guò)程,觸發(fā)器,自定義函數(shù)等。在本文中,將以C#來(lái)創(chuàng)建存儲(chǔ)過(guò)程。為什么不用T-SQL來(lái)創(chuàng)建存儲(chǔ)過(guò)程呢?因?yàn)門(mén)-SQL發(fā)展到目前,已經(jīng)很長(zhǎng)時(shí)間了,在某些場(chǎng)合有其局限性,比如T-SQL不是面向?qū)ο蟮?#xff0c;某些語(yǔ)法過(guò)于復(fù)雜等。而如果使用面向?qū)ο蟮?NET 語(yǔ)言來(lái)編寫(xiě)如存儲(chǔ)過(guò)程等數(shù)據(jù)對(duì)象時(shí),由于.net 語(yǔ)言強(qiáng)大的特性,因此能寫(xiě)出更健壯和更優(yōu)秀的存儲(chǔ)過(guò)程。注意,通過(guò)SQL Server 2005用.NET編寫(xiě)的存儲(chǔ)過(guò)程,都是和用.NET語(yǔ)言編寫(xiě)一般應(yīng)用的程序一樣,都是managed code。此外,CLR 編程語(yǔ)言提供了 T-SQL 中所沒(méi)有的豐富構(gòu)造(例如數(shù)組和列表等)。與 T-SQL(它是一種解釋語(yǔ)言)相比,CLR 編程語(yǔ)言之所以具有更好的性能,是因?yàn)橥泄艽a是已編譯的。對(duì)于涉及算術(shù)計(jì)算、字符串處理、條件邏輯等的操作,托管代碼的性能可能要優(yōu)于 T-SQL 一個(gè)數(shù)量級(jí)。在本文中,雖然可以用T-SQL來(lái)編寫(xiě)存儲(chǔ)過(guò)程,但為了說(shuō)明問(wèn)題,還是以C#來(lái)寫(xiě)存儲(chǔ)過(guò)程。步驟如下:
首先,打開(kāi)Visual Studio 2005 beta 2,選擇c#語(yǔ)言,新建立一個(gè)database工程,命名為sqlproject1。此時(shí),Visual Studio 2005 beta 2會(huì)詢問(wèn)你,要與什么數(shù)據(jù)庫(kù)進(jìn)行關(guān)聯(lián)。由于我們采用的是pubs這個(gè)數(shù)據(jù)庫(kù),因此我們選擇機(jī)器名是本地機(jī)器,設(shè)置好sql的驗(yàn)證方式,選擇pubs數(shù)據(jù)庫(kù),就可以了。(注意,在SQL Server 2005中,pubs和northwind數(shù)據(jù)庫(kù)不再是SQL Server 2005的自帶數(shù)據(jù)庫(kù)了,需要到http://go.microsoft.com/fwlink/?LinkId=31995去下載)。接著,在工程建立完畢后,選擇新增項(xiàng)目,選擇store procedure存儲(chǔ)過(guò)程,并以Authors.cs命名,再按確定,并輸入以下代碼:
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void GetAuthors()
{
SqlPipe sp = SqlContext.Pipe;
using (SqlConnection conn = new SqlConnection("context connection=true"))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.CommandText = "Select DatePart(second, GetDate()) " + " As timestamp,* from authors";
SqlDataReader rdr = cmd.ExecuteReader();
sp.Send(rdr);
}
}
[SqlProcedure]
public static void GetTitlesByAuthor(string authorID)
{
string sql = "select T.title, T.price, T.type, " + "T.pubdate from authors A" +
" inner join titleauthor TA on A.au_id = TA.au_id " +
" inner join titles T on TA.title_id = T.title_id " +
" where A.au_id = ’" + @authorID + "’";
using (SqlConnection conn = new SqlConnection("context connection=true"))
{
conn.Open();
SqlPipe sp = SqlContext.Pipe;
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.CommandText = sql;
SqlParameter paramauthorID = new SqlParameter("@authorID", SqlDbType.VarChar, 11);
paramauthorID.Direction = ParameterDirection.Input;
paramauthorID.Value = authorID;
cmd.Parameters.Add(paramauthorID);
SqlDataReader rdr = cmd.ExecuteReader();
sp.Send(rdr);
}
}
}
讓我們來(lái)看上面的代碼。首先聲明了Authors類,并且要引入System.Data.Sql;,System.Data.SqlTypes;,Microsoft.SqlServer.Server; System.Data.SqlClient等命名空間。其中,在Microsoft.SqlServer.Server命名空間中,有兩個(gè)十分重要的類:
·SqlContext: 一個(gè)SqlContext類包含的方法可以取得一個(gè)數(shù)據(jù)庫(kù)實(shí)例連接、命令,事務(wù)等。
·SqlPine: 用戶實(shí)現(xiàn)發(fā)送查詢結(jié)果和消息到客戶端,和ADO.NET里面的Response類有很多相似之處。
在Authors類中包含了兩個(gè)靜態(tài)方法,分別是GetAuthors和GetTitlesByAuthor。其中,GetAuthors方法返回pubs數(shù)據(jù)庫(kù)中authors表的所有數(shù)據(jù),而GetTitlesByAuthor,則返回指定作者的所寫(xiě)的圖書(shū)。
在GetAuthors方法中,首先通過(guò)調(diào)用sqlContext類的pipe屬性引用SqlPine對(duì)象:
SqlPipe sp = SqlContext.Pipe;
接著,使用SqlConnection對(duì)象連接到數(shù)據(jù)庫(kù)。注意,在連接數(shù)據(jù)庫(kù)的字符串中,使用"context=true",表示使用已經(jīng)登陸到數(shù)據(jù)庫(kù)的用戶進(jìn)行登陸:
using (SqlConnection conn = new SqlConnection("context connection=true"))
conn.Open();?
再創(chuàng)建SqlCommand對(duì)象的實(shí)例,并且設(shè)置其屬性:
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.CommandText = "Select DatePart(second, GetDate()) " + " As timestamp,* from authors";?
通過(guò)調(diào)用SqlCommand對(duì)象的ExecuteReader方法來(lái)執(zhí)行SQL語(yǔ)句。
SqlDataReader rdr = cmd.ExecuteReader();?
最后,使用SqlPipe對(duì)象,將結(jié)果集返回 到客戶端。這可以使用Send方法實(shí)現(xiàn)
sp.Send(rdr);?
要注意的是,我們?cè)趧?chuàng)建存儲(chǔ)過(guò)程后,必須對(duì)其進(jìn)行部署。我們先選擇builde菜單中的 build sqlproject1,就會(huì)編譯我們剛才創(chuàng)建的類。當(dāng)編譯完工程后,就可以進(jìn)行部署了。部署也十分簡(jiǎn)單,選擇build菜單,然后選擇Deploy sqlproject1,這樣就會(huì)自動(dòng)將剛寫(xiě)好的存儲(chǔ)過(guò)程部署到SQL Server 2005中去。
最后,我們還要在SQL Server management studio中,執(zhí)行如下語(yǔ)句,以確保在SQL Server 中可以執(zhí)行托管代碼:
EXEC sp_configure ’clr enabled’, 1;
RECONFIGURE WITH OVERRIDE;
GO?
利用TableAdapter Configuration Wizard創(chuàng)建數(shù)據(jù)訪問(wèn)層
在Visual Studio 2005 中,新增了TableAdapter configuration wizard來(lái)很方便地創(chuàng)建數(shù)據(jù)訪問(wèn)層。首先,我們了解下什么是tableadapter。一個(gè)tableadapter連接到數(shù)據(jù)庫(kù),執(zhí)行查詢語(yǔ)句或者存儲(chǔ)過(guò)程,并且將返回的結(jié)果集填充到datatable中去。Tableadapter configuration 向?qū)г试S你以類型化dataset方式創(chuàng)建編輯數(shù)據(jù)集合,十分方便。
首先用C#語(yǔ)言,創(chuàng)建一個(gè)名為NtierExample的Web項(xiàng)目,如下圖:
為了創(chuàng)建數(shù)據(jù)訪問(wèn)層,首先鼠標(biāo)右鍵點(diǎn)選工程項(xiàng)目菜單,在彈出的菜單中選擇"ADD New Item"。在彈出的"ADD NEW ITEM"對(duì)話框中,選擇"dataset"類型。然后在文件名中,輸入"Authors.xsd",并點(diǎn)擊"Add",如下圖所示:
當(dāng)你點(diǎn)"ADD"的按鈕時(shí) ,系統(tǒng)會(huì)提示是否將該文件放到APP_CODE目錄中去,因?yàn)?font color="#3366cc">VS.net 2005中,一般會(huì)將數(shù)據(jù)訪問(wèn)層的文件放到該文件夾中去,以方便管理。我們繼續(xù)選"ok",將xsd文件放到app_code文件夾中去。接下來(lái),就出現(xiàn)"TableAdpater"設(shè)置向?qū)У拇翱诹恕J紫?#xff0c;我們要指定連接的數(shù)據(jù)庫(kù)字符串,并選擇將連接字符串保存到web.config文件中去,并選"next"進(jìn)入下一步。
在該步中,選擇命令類型,由于我們剛才建立了存儲(chǔ)過(guò)程,因此選擇"Use existing store procedure",如下圖:
| ? |
再點(diǎn)選"NEXT",進(jìn)入下一個(gè)窗口,會(huì)詢問(wèn)采用哪一個(gè)存儲(chǔ)過(guò)程,如下圖:
這里,我們選擇使用"GetAuthors"這個(gè)存儲(chǔ)過(guò)程,再選"next"進(jìn)入下一步,如下圖:
在這里,我們要指定使用GetAuthors存儲(chǔ)過(guò)程的哪一個(gè)方法用來(lái)返回?cái)?shù)據(jù)集,我們選擇"return a datatable"的選現(xiàn),并指定使用其中的GetAuthors方法,以datatable的形式返回。繼續(xù)選"next",出現(xiàn)如下窗口,則系統(tǒng)自動(dòng)會(huì)生成數(shù)據(jù)訪問(wèn)層了。
當(dāng)你點(diǎn)擊"Finish"按鈕后,Visual Studio 會(huì)自動(dòng)產(chǎn)生一些類,當(dāng)這些類產(chǎn)生后,我們將類改名為Authors,這樣,最后輸出如下圖所示:
接下來(lái),我們按上面的步驟,類似地,使用"TableAdapter"向?qū)?#xff0c;選擇工具菜單欄的"Data-Add-TableAdapter",再次增加一個(gè)tableadapter,這次選擇的是"GetTitlesByAuthor"存儲(chǔ)過(guò)程,而選擇返回的方法是"GetTitlesByAuthor",其他步驟和生成"GetAuthos"的一樣,最后,將產(chǎn)生的類的名改為"AuthorTitles",如下圖所示
創(chuàng)建邏輯層
接下來(lái),我們創(chuàng)建邏輯層,在這個(gè)例子中,邏輯層是十分簡(jiǎn)單的,只是起到說(shuō)明作用。首先,我們新建一個(gè)類AuthroBiz類,并將其放在App_code文件夾中,并將類的代碼修改如下:
public class AuthorsBiz
{
public AuthorsBiz()
{}
public DataTable GetAuthors()
{
AuthorsTableAdapters.AuthorsTableAdapter authorDB = new AuthorsTableAdapters.AuthorsTableAdapter();
return authorDB.GetAuthors();
}
public DataTable GetAuthorTitles(string authorID)
{
AuthorsTableAdapters.AuthorTitlesTableAdapter authorDB = new AuthorsTableAdapters.AuthorTitlesTableAdapter();
return authorDB.GetTitlesByAuthor(authorID);
}
}
從上面的代碼中,可以看到,我們剛才通過(guò)向?qū)?chuàng)建的"Authors.xsd"類型化dataset類,現(xiàn)在在代碼中,可以通過(guò)使用AuthorsTableAdapters類來(lái)調(diào)用,其中authorDB是AuthorsTableAdapters類的實(shí)例。
創(chuàng)建表示層
在ASP.net 2.0中,在創(chuàng)建表示層時(shí),可以使用master-page技術(shù),使得可以很方便地構(gòu)建頁(yè)面。Mater-page的意思是,可以首先構(gòu)建出一個(gè)頁(yè)面的主框架模版結(jié)構(gòu),然后在其中放置一個(gè)ContentPlaceHolder控件,在該控件中,將展現(xiàn)其他子頁(yè)面的內(nèi)容。在其他子頁(yè)面中,只需要首先引用該master頁(yè)面,然后再修改ContentPlaceHolder控件的內(nèi)容就可以了。
首先,在工程中新增加一個(gè)"master"類型的文件,將其命名為CommonMaster,然后輸入以下代碼:
<%@ master language="C#" %>
<html>
<head id="Head1" runat="server">
<title>Master Page</title>
</head>
<body>
<form id="Form1" runat="server">
<table id="header" style="WIDTH: 100%; HEIGHT: 80px" cellspacing="1" cellpadding="1" border="1">
<tr>
<td style="TEXT-ALIGN: center; width: 100%; height: 74px;" bgcolor="teal">
<asp:label runat="server" id="Header" Font-Size="12pt" Font-Bold="True">
Authors Information
</asp:label>
</td>
</tr>
</table>
<b/>
<table id="leftNav" style="WIDTH: 108px; HEIGHT: 100%" cellspacing="1" cellpadding="1" border="1">
<tr>
<td style="WIDTH: 100px">
<table>
<tr>
<td>
<a href="Home.aspx">Home</a>
</td>
</tr>
<tr>
<td>
<a href="/Authors.aspx">Authors List</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table id="mainBody" style="LEFT: 120px; VERTICAL-ALIGN: top; WIDTH: 848px; POSITION: absolute; TOP: 94px; HEIGHT: 100%" border="1">
<tr>
<td width="100%" style="VERTICAL-ALIGN: top">
<asp:contentplaceholder id="middleContent" runat="Server"></asp:contentplaceholder>
</td>
</tr>
</table>
</form>
</body>
</html>
接下來(lái),我們首先創(chuàng)建以顯示作者頁(yè)面的Authors.aspx頁(yè)面,由于頁(yè)面的框架要保持一直,因此,可以利用maser-page技術(shù),在新建頁(yè)面時(shí),引入剛才建立的CommonMaster頁(yè)面,如下圖:
點(diǎn)ADD按鈕后,出現(xiàn)如下圖,選擇剛才建立的CommonMaster頁(yè)面,如下圖:
再輸入如下代碼:
<%@ Page Language="C#" MastERPageFile="~/CommonMaster.master" %>
<asp:content id="Content1" contentplaceholderid="middleContent" runat="server">
<asp:objectdatasource runat="server" id="authorsSource" typename="AuthorsBiz" selectmethod="GetAuthors">
</asp:objectdatasource>
<asp:gridview runat="server" AutoGenerateColumns="false" id="authorsView" datasourceid="authorsSource">
<alternatingrowstyle backcolor="Silver"></alternatingrowstyle>
<Columns>
<asp:HyPerlinkField DataTextField="au_id" HeaderText="Author ID" DataNavigateUrlFields="au_id"
DataNavigateUrlFormatString="AuthorTitles.aspx?AuthorID={0}">
</asp:HyperLinkField>
<asp:BoundField HeaderText="Last Name" DataField="au_lname"></asp:BoundField>
<asp:BoundField HeaderText="First Name" DataField="au_fname"></asp:BoundField>
<asp:BoundField HeaderText="Phone" DataField="phone"></asp:BoundField>
<asp:BoundField HeaderText="Address" DataField="address"></asp:BoundField>
<asp:BoundField HeaderText="City" DataField="city"></asp:BoundField>
<asp:BoundField HeaderText="State" DataField="state"></asp:BoundField>
<asp:BoundField HeaderText="Zip" DataField="zip"></asp:BoundField>
</Columns>
</asp:gridview>
</asp:content>
注意,其中我們用到了objectdatasource控件,在.NET 2.0中,有了該控件,可以很方便地溝通表示層和邏輯層。其中的代碼如下:
<asp:objectdatasource runat="server" id="authorsSource" typename="AuthorsBiz" selectmethod="GetAuthors">
</asp:objectdatasource>
其中的typename屬性指定為我們之前創(chuàng)建的邏輯層的類AuthorsBiz類,而為了獲得數(shù)據(jù),采用了selectmethod方法,這里指定了之前建立的GetAuthors方法。當(dāng)然,也可以在其他場(chǎng)合,應(yīng)用Updatemethod,Insertmethod,Deletemethod方法,也可以加上參數(shù),比如接下來(lái)要?jiǎng)?chuàng)建的AuthorTitle.aspx頁(yè)面,代碼如下:
<%@ Page Language="C#" MasterPageFile="~/CommonMaster.master" %>
<asp:content id="Content1" contentplaceholderid="middleContent" runat="server">
<asp:objectdatasource runat="server" id="authorTitlesSource" typename="AuthorsBiz" selectmethod="GetAuthorTitles">
<SelectParameters>
<asp:QueryStringParameter Type="String" Direction="Input" Name="authorID" QueryStringField="AuthorID" />
</SelectParameters>
</asp:objectdatasource>
<asp:gridview runat="server" id="authorTitlesView" datasourceid="authorTitlesSource">
<alternatingrowstyle backcolor="Silver"></alternatingrowstyle>
</asp:gridview>
</asp:content>
上面的代碼中,首先用戶在authors.aspx頁(yè)面點(diǎn)選某個(gè)作者名時(shí),則在authortitle.aspx頁(yè)面中,返回該作者的所有著作。所以,在objectdatasource控件中,我們使用了SelectParameters參數(shù),指定傳入來(lái)要查詢的參數(shù)是authorid。最后,再將gridview綁定到objectdatasource控件中去。
最后,運(yùn)行我們的代碼,結(jié)果如下兩圖所表示:
| |
小結(jié)
在ASP.NET 2.0中,我們利用SQL Server 2005的強(qiáng)大功能,可以利用.NET 語(yǔ)言創(chuàng)建存儲(chǔ)過(guò)程,并使用TableAdapter向?qū)?#xff0c;很方便地創(chuàng)建數(shù)據(jù)訪問(wèn)層,再利用objectdatasource控件的特性,可以很方便地溝通表示層和邏輯層。
轉(zhuǎn)載于:https://www.cnblogs.com/SoulStore/archive/2007/04/18/717907.html
總結(jié)
以上是生活随笔為你收集整理的ASP.NET2.0+SQL Server2005构建多层应用 [转]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。