Ado.net總結-Command(指揮官)
Command
- 概述
在 System.Data.SqlClient 名稱空間下,對應的 Command 類為 SqlCommand,在建立 SqlCommand 例項前必須已經建立了與資料庫的連線。
SqlCommand 類中常用的構造方法如下表所示:
構造方法 | 說明 |
---|---|
SqlCommand() | 無參構造方法 |
SqlCommand(string commandText,SqlConnection conn) | 帶參的構造方法,第 1 個引數是要執行的 SQL 語句,第 2 個引數是資料庫的連線物件 |
對資料庫中物件的操作不僅包括對資料表的操作,還包括對資料庫、檢視、儲存過程等資料庫物件的操作,接下來主要介紹的是對資料表和儲存過程的操作。
在對不同資料庫物件進行操作時,SqlCommand 類提供了不同的屬性和方法,常用的屬性和方法如下表所示:
屬性或方法 | 說明 |
---|---|
CommandText | 屬性,Command 物件中要執行的 SQL 語句 |
Connection | 屬性,獲取或設定資料庫的連線物件 |
CommandType | 屬性,獲取或設定命令型別 |
Parameters | 屬性,設定 Command 物件中 SQL 語句的引數 |
ExecuteReader() | 方法,獲取執行查詢語句的結果 |
ExecuteScalar() | 方法,返回查詢結果中第 1 行第 1 列的值 |
ExecuteNonQuery() | 方法,執行對資料表的增加、刪除、修改操作,返回影響的行數 |
使用Command類操作資料庫
Command 類中提供了 3 種命令型別,分別是 Text、TableDirect 以及 StoredProcedure,預設情況下是 Text。
所謂 Text 型別是指使用 SQL 語句的形式,包括增加、刪除、修改以及查詢的SQL語句。
StoredProcedure 用於執行儲存過程;TableDirect 僅在 OLE DB 驅動程式中有效。
在使用 Command 類操作資料庫時需要通過以下步驟完成。
1) 建立SqlCommand類的例項
建立 SqlCommand 類的例項分兩種情況,一種是命令型別為 Text 的,一種是命令型別為 StoredProcedure 的。命令型別為 Text
SqlCommand SqlCommand 類的例項名 = new SqlCommand( SQL 語句 , 資料庫連線類的例項 );
其中:
- SQL 語句:指該 SqlCommand 類的例項要執行的 SQL 語句。
資料庫連線類的例項:指使用 SqlConnection 類建立的例項,通常資料庫連線類的例項處於開啟的狀態。
命令型別為 StoredProcedure
SqlCommand SqlCommand 類的例項名 = new SqlCommand( 儲存過程名稱 , 資料庫連線類的例項 );
需要注意的是,儲存過程必須是當前資料庫例項中的儲存過程,並且在呼叫帶引數的儲存過程時,還需要在 SqlCommand 類的例項中新增對應的儲存過程引數。
為儲存過程新增引數,需要使用 SqlCommand 類例項的 Parameters 屬性來設定,具體的程式碼如下。
SqlCommand 類例項 .Parameters.Add( 引數名 , 引數值 );
2) 執行對資料表的操作
在執行對資料表的操作時通常分為兩種情況,一種是執行非查詢 SQL 語句的操作,即增加、修改、刪除的操作,一種是執行查詢 SQL 語句的操作。
執行非查詢 SQL 語句的操作
在執行非查詢 SQL 語句時並不需要返回表中的資料,直接使用 SqlCommand 類的 ExecuteNonQuery 方法即可,該方法的返回值是一個整數,用於返回 SqlCommand 類在執行 SQL 語句後,對錶中資料影響的行數。
當該方法的返回值為 -1 時,代表 SQL 語句執行失敗,當該方法的返回值為 0 時,代表 SQL 語句對當前資料表中的資料沒有影響。
例如 要刪除學號為 1100 的學生的資訊,而表中不存在該學號的學生的資訊,SQL語句可以正常執行,但對錶中的影響行數是 0。
具體的程式碼如下:
SqlCommand 類的例項 .ExecuteNonQuery();
需要注意的是,如果執行的 SQL 語句在資料庫中執行錯誤,則會產生異常,因此該部分需要進行異常處理。
執行查詢語句的操作
在執行查詢語句時通常需要返回查詢結果,SqlCommand 類中提供的 ExecuteReader 方法在執行查詢 SQL 語句後,會返回一個 SqlDataReader 型別的值,通過遍歷 SqlDataReader 類中的結果即可得到返回值。
具體的程式碼如下:
SqlDataReader dr = SqlCommand 類的例項 .ExecuteReader();
此外,如果在執行查詢語句後並不需要返回所有的查詢結果,而僅需要返回一個值,例如查詢表中的記錄行數,這時可以使用 ExecuteScalar 方法。具體的程式碼如下:
int returnvalue = SqlCommand 類的例項 .ExecuteScalar();
下面通過例項來演示 SqlCommand 類的使用:
- 先建立資料庫School,再建立表Student:
CREATE TABLE [dbo].[Student] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] VARCHAR (30) NOT NULL,
[Age] INT NULL,
[EnrollmentDate] DATE NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
這裡如果使用visual studio localdb時,插入中文會出現亂碼,解決方法可以參考這篇文章:
https://blog.csdn.net/xingkongtianyuzhao/article/details/103944280
下面是使用SqlCmd執行插入命令的示例:
這裡使用了引數化查詢SqlParameter,防止了sql注入
private void btnAddStudent_Click(object sender, EventArgs e)
{
string stuName = txtUserName.Text.Trim();
int stuAge = int.Parse(txtAge.Text.Trim());
DateTime stuEnrollMentDate = dtpEnrollmentDate.Value;
string strConn = Properties.Settings.Default.SchoolConn;
using (SqlConnection conn = new SqlConnection(strConn))
{
try
{
conn.Open();
string strSql = "insert into student(name,age,enrollmentdate) values(@name,@age,@enrollmentdate);";
SqlCommand cmd = new SqlCommand(strSql, conn);
cmd.Parameters.AddWithValue("@name", stuName);
cmd.Parameters.AddWithValue("@age", stuAge);
cmd.Parameters.AddWithValue("@enrollmentdate", stuEnrollMentDate);
int result = cmd.ExecuteNonQuery();
if (result != -1)
{
MessageBox.Show("註冊成功!");
}
else
{
MessageBox.Show("註冊失敗!");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
- 下面是使用SqlCmd執行查詢命令的示例:
private void btnSearchStudent_Click(object sender, EventArgs e)
{
string strName = txtStudentName.Text.Trim();
string strConn = Properties.Settings.Default.SchoolConn;
using (SqlConnection conn = new SqlConnection(strConn))
{
try
{
string strSql = "select * from student where name=@name";
SqlCommand cmd = new SqlCommand(strSql, conn);
cmd.Parameters.AddWithValue("@name", strName);
conn.Open();
var reader = cmd.ExecuteReader();
//兩種方式查詢
while (reader.Read())
{
MessageBox.Show("Id: " + reader.GetInt32(0).ToString());
MessageBox.Show("姓名: " + reader.GetString(1).ToString());
MessageBox.Show("年齡: " + reader.GetInt32(2).ToString());
MessageBox.Show("入學日期: " + reader.GetDateTime(3).ToString("yyyy-MM-dd"));
string result = "Id: " + reader[0] + "姓名:" + reader[1];
MessageBox.Show(result);
}
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
** 注意ExecuteScalar,ExecuteNoQuery,ExecuteReader的區別 **
- ExecuteNonQuery():執行命令物件的SQL語句,返回一個int型別變數,如果SQL語句是對資料庫的記錄進行操作(如記錄的增加、刪除和更新),那麼方法將返回操作所影響的記錄條數。
- ExecuteScalar():執行命令物件的SQL語句,如果SQL語句是SELECT查詢,則僅僅返回查詢結果集中的第1行第1列,而忽略其他的行 和列。該方法所返回的結果為object型別,在使用之前必須強制轉換為所需的型別。如果SQL語句不是SELECT查詢,則返回結果沒有任何作用。
- ExecuteReader():執行命令物件的SQL語句,在ADO.NET中,就是DataReader 物件的ExecuteReader()方法來進行資料的列出,並且我們用這個ExecuteReader()方法來顯示資料是最快的一種方法,只可以一條一條向前讀,不能返回。資料連線關閉,reader資料消失。
** 記憶:**
- ExecuteNonQuery:Query是查詢的意思,NonQuery就是不用於查詢,所以ExecuteNonQuery 除了查詢,可以執行增刪改語句;
- ExecuteScalar: Scalar是遊標意思,可以想象成釣魚的浮標,是用來釣資料的,一般用於查詢,而且釣魚一般一條一條掉,所以只返回第一行第一列的資料;
- ExecuteReader: 閱讀資料,想象成圖書,從前往後翻頁,但是它翻臉不認人,不能從後往前翻頁,而且翻臉速度特別快(查詢快);
- Command要記住防止SQL注入,最好用引數化查詢,就像釣魚的魚餌,不同的魚得用專用魚餌,投其所好,防止調上水母啥的,魚餌要放在SqlParameter裡面。
- 上一節把Command比喻為指揮官,指揮官得知道武器庫的地址,所以初始化的時候要給他,SqlConnection;還有指揮命令,Command指揮戰鬥的兩種形式(執行命令):嘴喊(Text),簡單直接;錄音(StoredProcedure):步驟太多,嘴喊類,錄下來,按個按鈕就播放,所以任命指揮官需要兩個要素:執行命令的形式和資料庫地址。你記住了嗎???