版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 研學(xué)旅行課程設(shè)計池州
- 煤氣化設(shè)備運行中的故障診斷與維修操作考核試卷
- 會員制度與大數(shù)據(jù)應(yīng)用考核試卷
- 煉焦配煤專家系統(tǒng)的應(yīng)用考核試卷
- 社區(qū)公共區(qū)域清潔考核試卷
- 礦山地質(zhì)災(zāi)害防治與預(yù)警的研究與應(yīng)用考核試卷
- 氣體分離過程中材料選擇與腐蝕控制考核試卷
- 盾構(gòu)機施工中的隧道工程規(guī)劃與設(shè)計方法研究考核試卷
- 社區(qū)兒童保護宣傳考核試卷
- 邀請函保證書
- 山東各市2022年中考物理試題及答案
- 醫(yī)療器械質(zhì)量記錄和追溯管理制度
- 華為認(rèn)證智能協(xié)作中級HCIP-CollaborationH11-861考試題及答案
- unit 5(單元測試)-2024-2025學(xué)年人教PEP版英語三年級上冊
- 2024年中國紅菜薹市場調(diào)查研究報告
- 報建協(xié)議書模板
- 山東虛擬電廠商業(yè)模式介紹
- 2024-2030年中國立式輥磨機行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略分析報告
- 保密工作履職報告?zhèn)€人
- 七年級生物上冊 2.1.1 練習(xí)使用顯微鏡教案 (新版)新人教版
- 2024年深圳市房屋租賃合同參考模板(5篇)
評論
0/150
提交評論