1. 程式人生 > >Ado.net總結-Command(指揮官)

Ado.net總結-Command(指揮官)

Command

  1. 概述
    在 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() 方法,執行對資料表的增加、刪除、修改操作,返回影響的行數
  1. 使用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 類的使用:

  1. 先建立資料庫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

  1. 下面是使用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);
        }

}
  1. 下面是使用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):步驟太多,嘴喊類,錄下來,按個按鈕就播放,所以任命指揮官需要兩個要素:執行命令的形式和資料庫地址。你記住了嗎???