《Visual C# NET案例教程》課件第7章_第1頁
《Visual C# NET案例教程》課件第7章_第2頁
《Visual C# NET案例教程》課件第7章_第3頁
《Visual C# NET案例教程》課件第7章_第4頁
《Visual C# NET案例教程》課件第7章_第5頁
已閱讀5頁,還剩123頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

第7章用戶登錄

7.1用戶登錄窗體介紹7.2Windows程序基礎(chǔ)7.3登錄窗體界面設(shè)計7.4ADO.NET數(shù)據(jù)庫操作7.5登錄功能實現(xiàn)7.6使用帶參數(shù)的Command實現(xiàn)登錄7.7調(diào)用存儲過程實現(xiàn)登錄7.8異常處理7.9知識拓展7.10習(xí)題

用戶登錄是圖書管理系統(tǒng)的一個基本功能,只有合法的用戶才能進入系統(tǒng)。在如圖7-1所示的登錄窗體中輸入用戶名與口令,與數(shù)據(jù)庫中信息進行驗證,如果合法,彈出登錄成功對話框,如圖7-2所示。7.1用戶登錄窗體介紹圖7-1初始界面圖7-2登錄成功

7.2.1第一個Windows程序

【例7-1】編寫、編譯并運行一個簡單的Windows應(yīng)用程序,用戶在編輯框中輸入文本后,單擊“確定”按鈕,輸入的信息顯示在頁面上。運行結(jié)果如圖7-3、圖7-4所示。7.2Windows程序基礎(chǔ)圖7-3初始界面

圖7-4例7-1運行效果

本例程序的編寫步驟如下:

(1)打開VisualStudio.NET開發(fā)環(huán)境IDE。

(2)在菜單中,單擊“文件”→“新建”→“項目”,彈出“新建項目”對話框。

(3)在“項目類型”列表框中選擇“VisualC#”;在“模板”列表框中選擇“Windows應(yīng)用程序”選項;其他采用默認(rèn),如圖7-5所示。圖7-5“新建項目”對話框(4)單擊“確定”按鈕,系統(tǒng)進入如圖7-6所示的窗體設(shè)計器的界面。圖7-6窗體設(shè)計器

(5)在左邊工具箱中拖入一個Button控件和一個TextBox控件;選中Button控件,在右下角的屬性窗口中設(shè)置控件的文本為“確定”,如圖7-7所示。圖7-7設(shè)計界面

(6)鼠標(biāo)雙擊“確定”按鈕,切換到代碼編輯界面,在光標(biāo)處輸入代碼,如圖7-8所示。圖7-8輸入代碼

(7)在菜單中選擇“調(diào)試”→“啟動調(diào)試”命令,系統(tǒng)編譯和運行該項目。7.2.2控件

控件是用于接受用戶輸入或在窗體上顯示某些信息的組件。每個控件都有自己的屬性、方法和事件,適合于完成某種特定的任務(wù)。

為了添加一個控件,可從工具欄上拖動控件并按照需要的位置將它放置在窗體上,也可以通過在工具欄上雙擊控件將控件加載到Windows窗體中。

Button控件是程序員在開發(fā)WindowsGUI程序時最常用的控件之一,Button允許用戶通過單擊Button控件來觸發(fā)操作。

Label控件主要用來在軟件界面上顯示說明性或提示性的文字,但不可以作為信息的輸入界面。

TextBox控件的主要功能是為運行的程序提供輸入數(shù)據(jù),用戶可以通過它輸入各種字符數(shù)據(jù)。TextBox控件的常用屬性見表7-1。TextBox控件的TextChanged事件表示文本框中的當(dāng)前內(nèi)容更改時觸發(fā)的操作。表7-1TextBox控件主要屬性7.2.3事件

Windows窗體編程模型基于事件。在WindowsForms程序中,幾乎大多數(shù)用戶的操作都將產(chǎn)生Windows事件,如按一個按鈕引發(fā)一個單擊(Click)事件,用戶移動鼠標(biāo)對應(yīng)鼠標(biāo)移動事件等;有一些事件不是由用戶操作產(chǎn)生的,而是由系統(tǒng)自動產(chǎn)生的,如數(shù)據(jù)庫鏈接斷開、時間到達(dá)某一時刻或是使用外設(shè)時未就緒等。

為了處理事件,應(yīng)用程序必須為該事件注冊一個事件處理方法。程序員就是通過書寫事件的響應(yīng)方法(即事件所引發(fā)的操作)來達(dá)到對程序的控制和交互的。例如,為一個按鈕的Click事件添加響應(yīng)方法的代碼:

button1.Click+=newSystem.EventHandler(MyMethod);

其中,MyMethod函數(shù)的定義如下:

voidMyMethod(objectsender,System.EventArgs)

當(dāng)用戶單擊該按鈕或者是使用其他方法引發(fā)Click事件時,MyMethod函數(shù)中的代碼將執(zhí)行。

事件處理方法都有一定的格式,常見格式如下:

privatevoid對象名_事件名(objectsender,EventArgse)

{

… //事件處理程序代碼主體

}7.2.4窗體

窗體是所有控件的容器,在窗體設(shè)計器中進行界面設(shè)計時,可以利用控件工具在它之上直觀地創(chuàng)建各種對象,并進行程序界面設(shè)計。一般的Windows程序都有一個窗體,可以把各種各樣的控件(如標(biāo)簽、文本框、命令按鈕等)放置在窗體上,組成一個非常人性化的人機界面。使用窗體只需從System.Windows.Forms類或其派生類中創(chuàng)建一個對象即可。窗體主要事件見表7-2。表7-2窗體主要事件下面的代碼是C#?中一個非常簡單的繼承Form(窗體)類的例子:

publicclassmyForm:System.Windows.Forms

{

privateSystem.Windows.Forms.Buttonbutton1;

publicmyForm(){}

}下面實現(xiàn)登錄窗體程序loginV1.0,本程序暫時不考慮與數(shù)據(jù)庫交互。運行該程序,輸入用戶名與口令,單擊“確定”按鈕,彈出對話框,顯示輸入的用戶名與口令,如圖7-9所示。7.3登錄窗體界面設(shè)計圖7-9登錄成功

loginV1.0的實現(xiàn)步驟如下:

(1)新建一個Windows應(yīng)用程序項目login。

(2)從“工具箱”向窗體拖入兩個Label控件、兩個編輯框控件、兩個按鈕,設(shè)置見表7-3。設(shè)計界面如圖7-10所示。圖7-10界面設(shè)計表7-3控件設(shè)置

(3)使用ToolTip顯示提示信息。

TooITip控件為窗體控件顯示簡短的信息,當(dāng)將鼠標(biāo)指向該控件時,相應(yīng)的提示信息就會顯示。

如圖7-11所示,當(dāng)鼠標(biāo)移到用戶名對應(yīng)編輯框時,會出現(xiàn)“用戶名不能為空”的提示。

ToolTip控件的SetToolTip()方法用于設(shè)置提示文本。TooITip的AutomaticDelay用于設(shè)置提示出現(xiàn)前所需的時間(毫秒),默認(rèn)值為500。圖7-11控件提示使用ToolTip控件實現(xiàn)提示的步驟如下:

從“工具箱”向窗體拖入一個TooITip控件,然后在窗體空白處雙擊,為Form的Load事件編寫代碼:

privatevoidForm1_Load(objectsender,EventArgse)

{

toolTip1.SetToolTip(txtPWD,"口令不能為空");

toolTip1.SetToolTip(txtUserName,"用戶名不能為空");

}

(4)使用ErrorProvider驗證輸入。

ErrorProvider控件用于指示窗體上的控件具有的關(guān)聯(lián)錯誤,當(dāng)用戶輸入無效數(shù)據(jù)時,顯示錯誤。

如果未輸入口令,單擊登錄,在口令旁邊會出現(xiàn)閃爍的感嘆號圖標(biāo),提示錯誤,鼠標(biāo)移到圖標(biāo)上,顯示“口令不能為空”的提示,如圖7-12所示。

當(dāng)在應(yīng)用程序的代碼中識別出一個錯誤時,為了顯示錯誤消息,可以使用ErrorProvider控件的SetError()方法。SetError()有兩個參數(shù):控件和將要顯示的消息。為了取消錯誤圖標(biāo)的顯示,可以使用ErrorProvider的clear()方法。圖7-12錯誤提示使用ErrorProvider驗證輸入的步驟如下:

從“工具箱”向窗體拖入一個ErrorProvider控件,雙擊“登錄”按鈕,為其Click事件編寫代碼:

privatevoidbtnLogin_Click(objectsender,EventArgse)

{

errorProvider1.Clear();

if(txtPWD.Text.Trim()=="")

errorProvider1.SetError(txtPWD,"口令不能為空");

if(txtUserName.Text.Trim()=="")

errorProvider1.SetError(txtUserName,"用戶名不能為空");

MessageBox.Show("用戶名為:"+txtUserName.Text+"口令為:"+txtPWD.Text);

}

(5)雙擊“取消”按鈕,為其Click事件編寫代碼:

privatevoidbtnCancel_Click(objectsender,EventArgse)

{

Close();

}7.4.1ADO.NET基本概念

目前大多數(shù)應(yīng)用程序都需要數(shù)據(jù)庫,可以將數(shù)據(jù)庫理解為計算機中用于存儲數(shù)據(jù)的倉庫。將各種數(shù)據(jù)按照某種組織方式存入數(shù)據(jù)庫后,既便于管理,又便于處理。與倉庫需要管理人員與管理制度一樣,數(shù)據(jù)庫也需要一個管理系統(tǒng),這個管理系統(tǒng)被稱為數(shù)據(jù)庫管理系統(tǒng)(DataBaseManagementSystem,DBMS)。ADO.NET是NETFramework用于數(shù)據(jù)訪問的組件,ADO.NET由MicrosoftActiveXDataObjects(ADO)改進而來,提供了平臺互用和可收縮的數(shù)據(jù)訪問功能。7.4ADO.NET數(shù)據(jù)庫操作

ADO.NET的一個重要優(yōu)點是可以以離線方式操作數(shù)據(jù)庫。傳統(tǒng)的主從式應(yīng)用程序在執(zhí)行時,都會保持和數(shù)據(jù)源的聯(lián)機。ADO.NET被設(shè)計成可以對斷開的數(shù)據(jù)集操作,應(yīng)用程序只有在要取得數(shù)據(jù)或是更新數(shù)據(jù)的時候才對數(shù)據(jù)源進行聯(lián)機,所以可以減少應(yīng)用程序?qū)Ψ?wù)器資源的占用,提高應(yīng)用程序的效率。7.4.2ADO.NET對象模型

ADO.NETFramework針對不同的數(shù)據(jù)庫,提供了下面4種數(shù)據(jù)提供程序:

●?SQLServer.NETFramework數(shù)據(jù)提供程序。

●?OLEDB.NETFramework數(shù)據(jù)提供程序。

●?ODBC.NETFramework數(shù)據(jù)提供程序。

●?Oracle.NETFramework數(shù)據(jù)提供程序。

ADO.NET對象模型中有五個主要的組件,分別是Connection對象、Command對象、DataAdapter對象、DataSet對象以及DataReader對象。ADO.NET對象模型如圖7-13所示。圖7-13ADO.NET對象模型常用的數(shù)據(jù)提供者為SQLServer.NET和OLEDB。相應(yīng)地,ASP.NET提供了兩組數(shù)據(jù)操作組件,分別為OLEDB數(shù)據(jù)操作組件以及SQL數(shù)據(jù)操作組件。

每組數(shù)據(jù)操作組件內(nèi)都有Connection對象、Command對象、DataAdapter對象及DataReader對象。每一個.NET數(shù)據(jù)提供者中定義的對象,其名稱前帶有相應(yīng)提供者的名稱,即用前綴OleDb以及SQL區(qū)分,見表7-4。表7-4OLEDB數(shù)據(jù)操作組件和SQL數(shù)據(jù)操作組件7.4.3SqlConnection對象

要存取數(shù)據(jù)源中的數(shù)據(jù),首先要建立程序和數(shù)據(jù)源之間的連接,Connection對象是連接程序和數(shù)據(jù)庫的“橋梁”。

對應(yīng)不同的數(shù)據(jù)提供者類型,常用的Connection對象有兩種:用于MicrosoftSQLServer數(shù)據(jù)庫的是SqlConnection;對于其他類型可以用OLEDB?.NET數(shù)據(jù)提供者的OleDbConnection。

SQLServer數(shù)據(jù)提供者提供的連接對象是SqlConnection,其連接字符串是以“鍵/值”對的形式組合而成的。連接字符串的常用屬性見表7-5。表7-5SqlConnection連接字符串的常用屬性

1.混合模式的連接

SQLServer數(shù)據(jù)庫混合模式的連接方式由用戶自己輸入登錄口令來連接到數(shù)據(jù)庫,可創(chuàng)建如下SqlConnection對象:

stringconnectionString="server=(local);database=pubs;uid=sa;pwd=";

SqlConnection

conn

=

new

SqlConnection(connectionString);

連接串為“server=(local);database=pubs;uid=sa;pwd=”,其含義是連接到本機SQLServer數(shù)據(jù)庫服務(wù)器中pubs數(shù)據(jù)庫,使用登錄名為sa,口令為空。注意其中uid、pwd分別為UserID、Password的簡寫。用這種方式創(chuàng)建SqlConnection對象需注意以下幾點:

(1)確保SQLServer數(shù)據(jù)庫設(shè)置為混合模式狀態(tài)。設(shè)置方式為在企業(yè)管理器中,右擊服務(wù)器圖標(biāo)→單擊“屬性”→在“SQLServer屬性(配置)”窗口中選中“安全性”選項卡→選中“身份驗證”中的“SQLServer與Windows”項,如圖7-14所示。圖7-14選中“身份驗證”中的“SQLServer與Windows”項單擊“確定”按鈕,彈出如圖7-15所示窗口,單擊“是”按鈕,讓服務(wù)器重新啟動。圖7-15單擊“是”按鈕讓服務(wù)器重新啟動

(2)連接串中的“Server”設(shè)置為SQLServer服務(wù)器名稱或IP地址,有時一臺機器可以不止安裝一個SQLServer服務(wù)器,這時需要以完整的機器名\SQLServer服務(wù)器名來表示,可以從SQLServer服務(wù)管理器中看到完整的名字,如圖7-16所示。

提示:此處我們利用了SQLServer缺省的登錄sa與口令,由于sa為系統(tǒng)的超級用戶,具有最高存取權(quán)限,為避免可能的破壞與提高系統(tǒng)的安全性,最好另建登錄,至少要為sa定義密碼。圖7-16查看完整的機器名\SQLServer服務(wù)器名

2.使用Windows驗證方式

以Windows驗證方式登錄SQLServer數(shù)據(jù)庫的SqlConnection對象,可用如下方式創(chuàng)建:

stringconnectionString="server=(local);database=pubs;trusted_connection=true";

SqlConnection

conn

=

new

SqlConnection

(connectionString);

該語句以信任方式連接到SQLServer,由于采用Windows驗證,因此無需給出登錄口令?!纠?-2】SqlConnection對象的創(chuàng)建與使用。

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Data;

usingSystem.Data.SqlClient;

namespaceconnection

{

classProgram

{

staticvoidMain(string[]args)

{

{

SqlConnectionconn=newSqlConnection("server=PC-0101005APPX;

database=BookDB;uid=sa;pwd=123");

conn.Open();

Console.WriteLine("連接成功!");

conn.Close();

}

}

}

}提示:

●本例要先建數(shù)據(jù)庫BookDB,BookDB數(shù)據(jù)庫在本書資源中提供,本書數(shù)據(jù)庫例子都在BookDB進行操作。

●如果使用了SQLServerProvider提供的對象,如SqlConnection、SqlCommand、SqlDataReader等,則一定要引入命名空間System.Data.SqlClient。

usingSystem.Data.SqlClient;

●在使用數(shù)據(jù)庫前要先用Open()方法打開連接,使用完數(shù)據(jù)庫后一定要及時調(diào)用Connection對象的Close()方法關(guān)閉連接,以節(jié)省對數(shù)據(jù)庫服務(wù)器資源的占用。7.4.4Command對象

Command對象主要用來對數(shù)據(jù)庫發(fā)出一些指令,通過Command對象可以對數(shù)據(jù)庫進行查詢、增加、修改、刪除等操作,以及調(diào)用數(shù)據(jù)庫中的存儲過程等。

建立Command對象的常用語法為:

OleDbCommandcmd=newOleDbCommand(cmdText,myConnection)

其中,cmdText用于描述需要進行的操作;myConnection用于指定所使用的連接對象。也可以用如下方式創(chuàng)建:

OleDbCommandcmd=myConnection.CreateCommand();

cmd.CommandText=cmdText;

Command對象的屬性見表7-6。表7-6Command對象的屬性Command對象的方法見表7-7。表7-7Command對象的方法【例7-3】增加、修改讀者表中的記錄。

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Data;

usingSystem.Data.SqlClient;

namespaceconnection

{

classProgram

{

staticvoidMain(string[]args)

{

{

//創(chuàng)建Connection

SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=BookDB;uid=sa;pwd=123");

//打開Connection

conn.Open();

//創(chuàng)建Command

SqlCommandcmd=newSqlCommand("update讀者表set姓名='丁三'where讀者編號='2'",conn);

//執(zhí)行Command命令

cmd.ExecuteNonQuery();

cmd.CommandText="insertinto讀者表values('06','李四','男','人文系','2');";

cmd.ExecuteNonQuery();

//關(guān)閉Connection

conn.Close();

}

}

}

}7.4.5DataReader對象

當(dāng)只需要從數(shù)據(jù)庫讀取數(shù)據(jù)而不需要修改時,可以使用DataReader對象,DataReader只能讀取數(shù)據(jù)而不能修改數(shù)據(jù)。DataReader每次以只讀的方式讀取一條記錄,因此節(jié)省資源而且效率高。

DataReader類是抽象類,因此不能直接實例化,而是要通過執(zhí)行Command對象的ExecuteReader方法返回DataReader實例。如:

OleDbDataReaderreader=cmd.ExecuteReader();

DataReader的常用屬性見表7-8。表7-8DataReader的常用屬性DataReader的常用方法見表7-9。表7-9DataReader的常用方法【例7-4】以下程序利用DataReader顯示圖書表中的記錄。

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Data;

usingSystem.Data.SqlClient;

namespaceconnection

{

classProgram

{

staticvoidMain(string[]args)

{SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=BookDB;uid=sa;pwd=123");

conn.Open();

SqlCommandcmd=newSqlCommand("select*from圖書表",conn);

SqlDataReaderdr=cmd.ExecuteReader();

while(dr.Read())

{

Console.WriteLine(dr["書名"].ToString()+"\t"+dr["作者"].ToString());

}

dr.Close();

conn.Close();

}

}

}程序說明:

在取得DataReader對象后,就可以將記錄中的數(shù)據(jù)取出使用。DataReader開始并沒有取回任何數(shù)據(jù),所以要先使用Read方法讓DataReader讀取一筆數(shù)據(jù)回來。如果DataReader對象成功取得數(shù)據(jù),則傳回True;若沒有取得數(shù)據(jù),則傳回False。

DataReader以獨占方式使用Connection對象,在關(guān)閉DataReader以前,無法對Connection對象執(zhí)行任何操作。所以,當(dāng)讀完數(shù)據(jù)時或不再使用DataReader時,要記住關(guān)閉DataReader。此外,要訪問相關(guān)Command對象的任何輸出參數(shù)或返回值時,也必須在關(guān)閉DataReader后才可行。

DataReader對象的Close方法只關(guān)閉DataReader對象本身,要關(guān)閉與其相關(guān)聯(lián)的Connection對象,則還需要調(diào)用Connection對象的Close方法。

當(dāng)調(diào)用Command對象的ExecuteReader方法時,將其Behavior參數(shù)的值指定為CommandBehavior.CloseConnection,則表示當(dāng)關(guān)閉DataReader對象時,相關(guān)聯(lián)的Connection對象也隨之關(guān)閉。如:

SqlDataReaderdr=cmd.ExecuteReader(CommandBehavior.CloseConnection);

上述代碼行的作用是,當(dāng)調(diào)用Close方法關(guān)閉DataReder時,系統(tǒng)會隱式地關(guān)閉底層連接。下面利用前面介紹的幾個ADO.NET對象來實現(xiàn)login的登錄功能的方法。

loginV2.0的實現(xiàn)步驟如下:

(1)打開loginV1.0項目。

(2)在Form1的代碼文件頭部加入“usingSystem.Data.SqlClient;”。7.5登錄功能實現(xiàn)(3)改寫“登錄”按鈕的單擊事件代碼如下:

privatevoidbtnLogin_Click(objectsender,EventArgse)

{

errorProvider1.Clear();

if(txtPWD.Text.Trim()=="")

errorProvider1.SetError(txtPWD,"口令不能為空");

if(txtUserName.Text.Trim()=="")

errorProvider1.SetError(txtUserName,"用戶名不能為空");

SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=bookdb;integrated

security=true");

stringsql="select口令from用戶表where用戶名='"+txtUserName.Text+"'";

SqlCommandcmd=newSqlCommand(sql,conn);

conn.Open();

SqlDataReaderreader=cmd.ExecuteReader();

if(reader.Read()&&reader.GetString(0)==txtPWD.Text)

{

MessageBox.Show("登錄成功!");

}

else

{

MessageBox.Show("登錄失敗!");

}

reader.Close();

conn.Close();

}對于程序運行中動態(tài)生成的SQL命令,可以使用參數(shù),需要用System.Data.SqlClient命名空間中的SqlParameter類,SqlParameter類的主要屬性見表7-10。7.6使用帶參數(shù)的Command實現(xiàn)登錄表7-10SqlParameter類的主要屬性ParameterDirection類型枚舉成員見表7-11。表7-11ParameterDirection類型枚舉成員【例7-5】在用戶表中增加一條記錄。

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Data;

usingSystem.Data.SqlClient;

namespaceconnection

{

classProgram

{

staticvoidMain(string[]args)

{//創(chuàng)建Connection

SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=BookDB;uid=sa;pwd=123");

//創(chuàng)建Command,SQL語句中有@UserName與@PWD兩個參數(shù)

SqlCommandcmd=newSqlCommand("insertinto用戶表values(@UserName,@PWD)",conn);

//把@UserName參數(shù)加入到Parameters,并給參數(shù)賦值

cmd.Parameters.Add("@UserName",SqlDbType.VarChar).Value="hello";

//把@PWD參數(shù)加入到Parameters,并給參數(shù)賦值

cmd.Parameters.Add("@PWD",SqlDbType.VarChar).Value="123";

//打開連接

conn.Open();

cmd.ExecuteNonQuery();

}

}

}下面利用帶參數(shù)的Command來實現(xiàn)login的登錄功能。

loginV3.0的實現(xiàn)步驟如下:

(1)打開loginV2.0項目。

(2)改寫“登錄”按鈕的單擊事件代碼如下:privatevoidbtnLogin_Click(objectsender,EventArgse)

{

errorProvider1.Clear();

if(txtPWD.Text.Trim()=="")

errorProvider1.SetError(txtPWD,"口令不能為空");

if(txtUserName.Text.Trim()=="")

errorProvider1.SetError(txtUserName,"用戶名不能為空");

SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=bookdb;integratedsecurity=true");

stringsql="select口令from用戶表where用戶名=@userName";

SqlCommandcmd=newSqlCommand(sql,conn);

cmd.Parameters.AddWithValue("@userName",txtUserName.Text);//給@userName參數(shù)賦值

conn.Open();

SqlDataReaderreader=cmd.ExecuteReader();try

{

if(reader.Read()&&reader.GetString(0)==txtPWD.Text)

{

MessageBox.Show("登錄成功!");

}

else

{

MessageBox.Show("登錄失?。?);

}

}

finally

{

reader.Close();

conn.Close();

}

}存儲過程(StoredProcedure)是由一系列SQL語句和控制語句組成的數(shù)據(jù)處理過程,這些SQL語句和和控制語句存放在數(shù)據(jù)庫中,在服務(wù)器端運行。由于存儲過程是已經(jīng)編譯好的,因此執(zhí)行存儲過程比用SQL語句的速度快。并且使用存儲過程可以提高數(shù)據(jù)操作的安全性。將命令編寫為存儲過程是改善數(shù)據(jù)驅(qū)動的應(yīng)用程序性能的常用技巧。7.7調(diào)用存儲過程實現(xiàn)登錄

ADO.NET中執(zhí)行存儲過程與執(zhí)行一般的SQL命令相似,不同的地方有以下兩點:

●創(chuàng)建Command時,命令語句CommandText為存儲過程名。

●?CommandType屬性值設(shè)置為CommandType.

StoredProcedure,表示要執(zhí)行存儲過程。

存儲過程參數(shù)有輸入?yún)?shù)、輸出參數(shù)和返回值,使用方法如下:

(1)輸入?yún)?shù)的用法。

//創(chuàng)建SqlParameter類型參數(shù),注意參數(shù)名@title_id要與存儲過程中的參數(shù)名一致。

SqlParameterparamid=newSqlParameter("@title_id",

SqlDbType.

NVarChar,50);

//給參數(shù)賦值

paramid.Value="BU1111";

//把參數(shù)加入到Command的Parameters集合

cmd.Parameters.Add(paramid);

(2)輸出參數(shù)的用法。

//創(chuàng)建SqlParameter類型參數(shù)

SqlParameterparamtitle=newSqlParameter("@title",SqlDbType.NVarChar,150);

//指出該參數(shù)是存儲過程的OUTPUT參數(shù)

paramtitle.Direction=ParameterDirection.Output;

//把參數(shù)加入到Command的Parameters集合

cmd.Parameters.Add(paramtitle);

(3)返回值的獲取。

//創(chuàng)建SqlParameter類型參數(shù)

SqlParameterparamreturn=newSqlParameter("@return",SqlDbType.Int,150);

//指出該參數(shù)是存儲過程的返回參數(shù)

paramreturn.Direction=ParameterDirection.ReturnValue;

//把參數(shù)加入到Command的Parameters集合

cmd.Parameters.Add(paramreturn);【例7-6】調(diào)用帶參數(shù)的存儲過程。

首先,在查詢分析器中運行如下的SQL語句,創(chuàng)建存儲過程p_2:

CREATEprocedurep_1

@BookIDvarchar(50), 書的編號

@BookNamevarchar(150)output 書名

As

Select@BookName=書名From圖書表where圖書編號=@BookID

if@@RowCount>0

return1找到書

else

return0未找到書上面的存儲過程的功能是根據(jù)用戶輸入的書的編號,如果找到書,則返回1,并用輸出參數(shù)回傳該書的書名;如果沒有找到書,則返回0。在該存儲過程中,@BookName后面的output關(guān)鍵字說明是一個輸出參數(shù)。由于使用了return語句,因此該存儲過程有返回值。

建立存儲過程后接著建立并運行下面的程序,該程序調(diào)用存儲過程p_2,傳入@BookID,并取回輸出參數(shù)@BookName的值和返回值。usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Data;

usingSystem.Data.SqlClient;

namespaceConsoleApplication2

{

classProgram

{

staticvoidMain(string[]args)

{

SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=bookdb;integratedsecurity=true");SqlCommandcmd=newSqlCommand(“p_1”,conn);

cmd.CommandType=CommandType.StoredProcedure;

SqlParameterparamid=newSqlParameter(“@BookID”,SqlDbType.

NVarChar,50);

paramid.Value="1";

cmd.Parameters.Add(paramid);

SqlParameterparamBookName=newSqlParameter("@BookName",SqlDbType.NVarChar,150);

//指出該參數(shù)是存儲過程的OUTPUT參數(shù)

paramBookName.Direction=ParameterDirection.Output;

cmd.Parameters.Add(paramBookName);

SqlParameterparamreturn=newSqlParameter("@return",SqlDbType.Int,150);

//指出該參數(shù)是存儲過程的返回參數(shù)paramreturn.Direction=ParameterDirection.ReturnValue;

cmd.Parameters.Add(paramreturn);

conn.Open();

cmd.ExecuteNonQuery();

conn.Close();

if(paramreturn.Value.ToString()==“0”)

Console.WriteLine(“書號為1的圖書不存在!”);

else

Console.WriteLine(“書號為1的書名為:”+paramBookName.

Value.ToString());

}

}

}LoginV4.0的實現(xiàn)步驟如下:

(1)首先在SqlServer數(shù)據(jù)庫中建立如下的登錄存儲過程:

createprocedurepr_login

@userNamevarchar(20), 用戶名

@pwdvarchar(10)--口令

as

declare@countint

select@count=count(*)from用戶表where用戶名=@userNameand口令@pwd

if@count>0

return1 成功

else

return0 失敗(2)打開loginV3.0項目,改寫“登錄”按鈕的單擊事件代碼如下:

privatevoidbtnLogin_Click(objectsender,EventArgse)

{

errorProvider1.Clear();

if(txtPWD.Text.Trim()=="")

errorProvider1.SetError(txtPWD,"口令不能為空");

if(txtUserName.Text.Trim()=="")

errorProvider1.SetError(txtUserName,"用戶名不能為空");

SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=bookdb;integratedsecurity=true");

SqlCommandcmd=newSqlCommand("pr_login",conn);

cmd.CommandType=CommandType.StoredProcedure;//說明該SqlCommand對應(yīng)存儲過程

cmd.Parameters.AddWithValue("@userName",txtUserName.Text);//給@userName參數(shù)賦值cmd.Parameters.AddWithValue("@pwd",txtPWD.Text);//給@pwd參數(shù)賦值

SqlParameterparamreturn=cmd.Parameters.Add("@return",SqlDbType.Int);//增加返回值參數(shù)

paramreturn.Direction=ParameterDirection.ReturnValue;//指出該參數(shù)是存儲過程的返回參數(shù)

conn.Open();

cmd.ExecuteNonQuery();

conn.Close();

if(paramreturn.Value.ToString()=="1")

MessageBox.Show("登錄成功!");

else

MessageBox.Show("登錄失敗!");

}7.8.1異常類型

在實際編程中,每個程序員編寫的代碼都不可避免地會出現(xiàn)這樣或那樣的錯誤。所謂異常,是指在程序運行期間發(fā)生的錯誤或意外情況。產(chǎn)生異常的常見原因有以下幾種:

●代碼的邏輯錯誤。如使用了無效的數(shù)組下標(biāo)、訪問了沒有分配內(nèi)存的對象、想要打開一個不存在的文件等。7.8異常處理●用戶的錯誤輸入。這是由于用戶不遵守程序本身規(guī)定的數(shù)據(jù)輸入格式所引起的。

●計算機的物理限制。由于硬盤和內(nèi)存的空間有限,而程序運行所需空間超出了這個限制,則程序運行時將產(chǎn)生異常。

●計算機外部設(shè)備錯誤。計算機的外部設(shè)備可能處于不正常的工作狀態(tài),如遠(yuǎn)程服務(wù)器運行不正?;虼蛴C電源沒打開等。

【例7-7】一個被零除異常例子,運行結(jié)果如圖7-17所示。

usingSystem;

publicclassDivideByZero

{

publicstaticvoidMain()

{

intx=0; //被除數(shù)

inty=10; //除數(shù)

intz=y/x; //引發(fā)被零除異常

Console.WriteLine("結(jié)果為"+z);

}

}圖7-17例7-7運行結(jié)果

C#定義了一些常見的異常類(見表7-12),程序員也可以自定義異常類。表7-12常見的異常類7.8.2Try…catch語句

try或catch語句塊不能單獨使用,它們必須同時使用。通常情況下,try配合多個catch子句,每個catch子句對應(yīng)一種特定的異常try/catch語句塊,其基本格式如下:

try

{

//可能產(chǎn)生異常的程序代碼

}

catch(異常類型1異常對象)

{

//處理異常類型1的異常控制代碼

}

catch(異常類型2異常對象)

{

//處理異常類型2的異??刂拼a

}當(dāng)try子句中的程序代碼產(chǎn)生異常時,系統(tǒng)就會在catch子句中查找,看是否有與設(shè)置的異常類型相同的catch子句。如果有,就會執(zhí)行該子句中的語句;如果沒有,則轉(zhuǎn)到調(diào)用當(dāng)前方法的函數(shù)中繼續(xù)查找。該過程一直繼續(xù)下去,直至找到一個匹配的catch子句為止。如果一直沒有找到,則運行時將會產(chǎn)生一個未處理的異常錯誤。

如果沒有發(fā)生異常,那么try塊正常結(jié)束,所有的catch語句被忽略,程序轉(zhuǎn)到最后一個catch語句之后的第一條語句處開始執(zhí)行。

catch子句也可以不包含參數(shù),即不包含對某種類型異常對象的捕獲。

【例7-8】?在下述的例子中產(chǎn)生了一個被零除異常,用try塊捕捉這個異常,然后由catch塊捕獲并控制出現(xiàn)的異常,并且讓程序正常結(jié)束。

usingSystem;

publicclassDivideByZero

{

publicstaticvoidMain()

{

intz=0;

Console.WriteLine("請輸入除數(shù):");

intx=int.Parse(Console.ReadLine());

inty=10;

try{

z=y/x; //可能產(chǎn)生異常的程序代碼

Console.WriteLine("結(jié)果為"+z);

}

catch(Exceptione)

{

Console.WriteLine("程序有錯誤!錯誤為:{0}",e.Message);

}

Console.WriteLine("運行完畢!");

}

}

運行結(jié)果如圖7-18所示。圖7-18例7-8運行結(jié)果7.8.3Try…finally語句

如果程序中使用了必須釋放的資源,如數(shù)據(jù)庫的連接,則可用try/finally塊來確保執(zhí)行釋放的資源方法。常見使用方式是,在try塊中獲取并使用資源,在catch塊中處理異常情況,并在finally塊中釋放資源。loginV5.0的實現(xiàn)步驟如下:

privatevoidbtnLogin_Click(objectsender,EventArgse)

{

errorProvider1.Clear();

if(txtPWD.Text.Trim()=="")

errorProvider1.SetError(txtPWD,"口令不能為空");

if(txtUserName.Text.Trim()=="")

errorProvider1.SetError(txtUserName,"用戶名不能為空");

SqlConnectionconn=newSqlConnection("server=.;database=bookdb;integratedsecurity=true");

stringsql="selectPWDfromuserswhereusername='"+txtUserName.Text+"'";SqlCommandcmd=newSqlCommand(sql,conn);

conn.Open();

SqlDataReaderreader=null;

try

{

reader=cmd.ExecuteReader();

if(reader.Read()&&reader.GetString(0)==txtPWD.Text)

{

MessageBox.Show("登錄成功!");

}

else

{

MessageBox.Show("登錄失??!");

}

}

catch //捕捉異常

{

MessageBox.Show("數(shù)據(jù)庫操作失??!");

}

finally //釋放資源

{

reader.Close();

conn.Close();

}

}7.8.4使用throw語句拋出異常

throw語句可用于拋出異常,其基本格式為

throw[異常類的對象];

使用throw語句還可以把由catch語句捕獲到的異常再次拋出,以便外部的catch塊捕獲。之所以再次拋出異常,主要的原因就是要靈活處理異常,再次拋出的異常不會被目前的catch語句捕獲到,但它會傳播到下一個catch語句?!纠?-9】用throw語句拋出異常。

usingSystem;

publicclassDivideByZero

{

publicstaticdoubledivide(intx,inty)

{

if(x==0)

{

thrownewException("對不起,除數(shù)不能為0!");//拋出異常

}

else

{

returny/x;

}

}publicstaticvoidMain()

{

try

{

Console.WriteLine("結(jié)果為:"+divide(0,10));

}

catch(Exceptione)

{

Console.WriteLine("發(fā)生錯誤,錯誤為:\n{0}",e.Message);

}

}

}

運行結(jié)果如圖7-19所示。圖7-19例7-9運行結(jié)果7.9.1ExecuteScalar方法

ExecuteScalar()方法用于返回執(zhí)行結(jié)果中首行首列的值,該方法只能執(zhí)行Select語句,一般用于取得最大值(Max)、最小值(Min)、平均值(Avg)、記錄數(shù)(Count)。

下面使用ExecuteScalar方法實現(xiàn)登錄功能。7.9知識拓展{

errorProvider1.Clear();

if(txtPWD.Text.Trim()=="")

errorProvider1.SetError(txtPWD,"口令不能為空");

if(txtUserName.Text.Trim()=="")

errorProvider1.SetError(txtUserName,"用戶名不能為空");

SqlConnectionconn=newSqlConnection("server=PC-20101005APPX;database=bookdb;integratedsecurity=true");

conn.Open();

stringsql="selectcount(*)from用戶表where用戶名='"+txtUserName.Text+"'and口令='"+txtPWD.Text+"'";

SqlCommandcmd=newSqlCommand(sql,conn);

intcount=(int)cmd.ExecuteScalar();

if(count>0)

{

MessageBox.Show("登錄成功!");

}

else

{

MessageBox.Show("登錄失??!");

}

conn.Close();

}7.9.2ListBox控件

ListBox控件顯示一個項列表,用戶可從中選擇一項或多項。Se

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論