ADO.NET入門教程(六) 談談Command對象與數據檢索


摘要

到目前為止,我相信大家對於ADO.NET如何與外部數據源建立連接以及如何提高連接性能等相關知識已經牢固於心了。連接對象作為ADO.NET的主力先鋒,為用戶與數據庫交互搭建了扎實的橋梁。它的一生是平凡而又偉大的,總是盡自己最大的努力為用戶搭建一條通往數據庫的平坦大道。相比連接對象來說,Command對象似乎耀眼的多。Command對象在ADO.NET世界里總是忙忙碌碌,它就像一個外交官,為用戶傳達了所有操作數據庫的信息。


目錄


1. 准備

      學習知識最快也最好的方法,那就是將理論與實踐相結合。為了幫助大家更好的理解和掌握Command對象,我也准備了很多實踐的例子。我希望大家能做好充分的准備,這樣的話不至於在實踐的時候手忙腳亂。您需要准備以下幾件事情:

(1)確保你的電腦裝有SQL Server 2005/2008數據庫服務器。如果未裝有SQL Server服務器,點此下載 SQL Server 2008 EXPRESS R2。

(2)創建一個名為db_MyDemo的數據庫。

USE master;
GO
CREATE DATABASE db_MyDemo
ON
(
NAME = MyDemo_data, /*指定文件的邏輯名稱*/
FILENAME = 'D:\mydemo_dat.mdf',/*物理文件名稱*/
SIZE = 10,/*指定文件大小,單位MB*/
MAXSIZE = 50,/*文件最大值,單位MB*/
FILEGROWTH = 5 /*自動增量*/
)
LOG ON
(
Name = MyDemo_log,
FILENAME = 'D:\mydemo_log.ldf',
SIZE = 5MB,
MAXSIZE = 25MB,
FILEGROWTH = 5MB
)
GO

(3)創建顧客表tb_SelCustomer。

use db_MyDemo;
GO
CREATE TABLE tb_SelCustomer
(
ID INT IDENTITY(1,1) PRIMARY KEY, /*ID,主鍵*/
Name varchar(20) NOT NULL, /*姓名*/
Sex char(1) default('0'), /*性別:0為男,1為女,默認為0*/
CustomerType char(1) default('0'), /*客戶類型:0為普通用戶,1為VIP用戶,默認為0*/
Phone varchar(12), /*聯系電話*/
Email varchar(50), /*電子郵件*/
ContactAddress varchar(200), /*聯系地址*/
Lat float, /*所在位置維度,用於在地圖顯示*/
Lng float, /*所在位置經度,用於在地圖顯示*/
Postalcode varchar(10), /*郵政編碼*/
Remark varchar(50) /*備注*/
)

 好了,恭喜你!終於把准備工作做好了。下面,讓我們一起來揭開Command對象的面紗!

 

2. 什么是Command對象?

      我們知道ADO.NET最主要的目的對外部數據源提供一致的訪問。而訪問數據源數據,就少不了增刪查改等操作。盡管Connection對象已經我們連接好了外部數據源,但它卻忠於職守,並不提供對外部數據源的任何操作。就在糾結萬分的時刻,Command對象誕生了。它封裝了所有對外部數據源的操作(包括增、刪、查、改等SQL語句與存儲過程),並在執行完成后返回合適的結果。與Connection對象一樣,對於不同的數據源,ADO.NET提供了不同的Command對象。具體來說,可分為以下Command對象。

.NET數據提供程序                                                                  對應Command對象                                                                                          
用於 OLE DB 的 .NET Framework 數據提供程序  OleDbCommand對象
用於 SQL Server 的 .NET Framework 數據提供程序  SqlCommand對象
用於 ODBC 的 .NET Framework 數據提供程序  OdbcCommand 對象
用於 Oracle 的 .NET Framework 數據提供程序  OracleCommand 對象

不管是哪種Command對象,它都繼承於DBCommand類。與DBConnection類一樣,DBCommand類也是抽象基類,不能被實例化,並期待派生類(對應於特定.NET數據提供程序的Command類)來實現方法。 DBCommand類定義了完善的健全的數據庫操作的基本方法和基本屬性,它的結構如下:

public abstract class DbCommand : Component, 
IDbCommand, IDisposable

從上面我們可以知道,它繼承了Component類以及IDbCommand接口和IDisposable接口。

 

3. 必須掌握的幾個屬性

 CommandText: 獲取或設置對數據源執行的文本命令。默認值為空字符串。

 CommandType: 命令類型,指示或指定如何解釋CommandText屬性。CommandType屬性的值是一個枚舉類型,定義結構如下:

public enum CommandType    
{ Text = 1, //SQL 文本命令。(默認。)
StoredProcedure = 4, // 存儲過程的名稱。
TableDirect = 512 //表的名稱。
}

需要特別注意的是,將CommandType 設置為 StoredProcedure 時,應將 CommandText 屬性設置為存儲過程的名稱。 當調用 Execute 方法之一時,該命令將執行此存儲過程。

Connection: 設置或獲取與數據源的連接。

Parameters: 綁定SQL語句或存儲過程的參數。參數化查詢中不可或缺的對象,非常重要。

Tranction: 獲取或設置在其中執行 .NET Framework 數據提供程序的 Command 對象的事務。

 

4. 必須掌握的幾個方法

 ExecuteNonQuery: 執行不返回數據行的操作,並返回一個int類型的數據。

 注意:對於 UPDATE、INSERT 和 DELETE 語句,返回值為該命令所影響的行數。 對於其他所有類型的語句,返回值 為 -1。

 ExecuteReader: 執行查詢,並返回一個 DataReader 對象。
 ExecuteScalar: 執行查詢,並返回查詢結果集中第一行的第一列(object類型)。如果找不到結果集中第一行的第一列,則返回 null 引用。

 

5. 如何創建Command對象?

      在創建Command對象之前,你需要明確兩件事情:(1)你要執行什么樣的操作?(2)你要對哪個數據源進行操作?明白這兩件事情,一切都好辦了。我們可用通過string字符串來構造一條SQL語句,也可以通過Connection對象指定連接的數據源。那么我們如何將這些信息交給Command對象呢?一般來說,有兩種方法:

(1)通過構造函數。代碼如下:

string strSQL = "Select * from tb_SelCustomer";
SqlCommand cmd = new SqlCommand(strSQL, conn);

(2)通過Command對象的屬性。代碼如下:

SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = strSQL;

提示:上面兩個實例是相對於SQL Server來說的,如果你訪問其他數據源,應當選擇其他的Command對象。具體參照 #2 什么是Command對象 中的表格。

 

6. 選擇合適的執行命令

      Command對象提供了豐富的執行命令操作,具體方法可參考 #4 必須掌握的幾個方法 。凡是有利有弊,Comandante對象既然提供多種執行命令,我們在實際開發中就要有所取舍,選擇合適的執行命令。其實,用戶對數據源的操作不外乎CRUD-S(Create、Update、Delete、Select)操作。下面我將探討如何在不同的場景選擇合適的執行命令。

(1)場景一:執行CRUD操作,不返回數據行,返回影響的行數(可選)

      當我們對數據表的行(記錄)進行增加,刪除,更新操作或者處理數據定義語句(比如用Create Table來創建表結構)時,實際上數據庫是不返回數據行的,僅僅返回一個包含影響行數信息的整數。一般地,在執行非查詢操作時,我們需要調用ExcuteNonQuery方法。還是,先看一個實例吧!我們在tb_SelCustomer表中插入一行記錄,代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;//必須引入
using System.Data.SqlClient;//必須引入

namespace Command
{
class Program
{
static void Main(string[] args)
{
string connSQL = @"Data Source=.\SQLEXPRESS; Initial Catalog=db_MyDemo; Integrated Security=SSPI";//構造連接字符串
SqlConnectionStringBuilder connStr = new SqlConnectionStringBuilder(connSQL);

using(SqlConnection conn = new SqlConnection(connStr.ConnectionString))
{
//拼接SQL語句
StringBuilder strSQL = new StringBuilder();
strSQL.Append("insert into tb_SelCustomer ");
strSQL.Append("values(");
strSQL.Append("'liuhao','0','0','13822223333','liuhaorain@163.com','廣東省深圳市寶安區',12.234556,34.222234,'422900','備注信息')");

Console.WriteLine("Output SQL:\n{0}",strSQL.ToString());

//創建Command對象
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = strSQL.ToString();

try
{
conn.Open();//一定要注意打開連接

int rows = cmd.ExecuteNonQuery();//執行命令
Console.WriteLine("\nResult: {0}行受影響",rows);
}
catch(Exception ex)
{
Console.WriteLine("\nError:\n{0}", ex.Message);
}
}

Console.Read();
}
}
}

 運行后,輸出結果如下:

從上面輸出信息我們可以看到,已經成功的添加一行數據。

(2)場景二:執行Select操作,返回多個數據

      當我們通過執行Select操作返回一行或多行數據時,這時候ExcuteNonQuery就需要休息了。不過也別慌,話說Command對象手下猛將如雲,處理這種事情就需要請ExcuteReader方法上場了。ExcuteReader方法返回一個DataReader對象。DataReader是一個快速的,輕量級,只讀的遍歷訪問每一行數據的數據流。使用DataReader時,需要注意以下幾點:

  • DataReader一次遍歷一行數據,並返回一個包含列名字集合。
  • 第一次調用Read()方法獲取第一行數據,並將游標指向下一行數據。當再次調用該方法時候,將讀取下一行數據。
  • 當檢測到不再有數據行時,Read()方法將返回false。
  • 通過HasRows屬性,我們知道查詢結果中是否有數據行。
  • 當我們使用完DataReader時,一定要注意關閉。SQL Server默認只允許打開一個DataReader。

好吧,還是先看一個簡單的例子吧。查詢出tb_SelCustomer表中所有的數據。代碼如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace Command2
{
class Program
{
static void Main(string[] args)
{
//構造連接字符串
SqlConnectionStringBuilder strConn = new SqlConnectionStringBuilder();
strConn.DataSource = @"(local)\SQLEXPRESS";
strConn.InitialCatalog = "db_MyDemo";
strConn.IntegratedSecurity = true;

using (SqlConnection conn = new SqlConnection(strConn.ConnectionString))
{
string strSQL = "select * from tb_SelCustomer";
SqlCommand cmd = new SqlCommand(strSQL, conn);//使用構造函數方式創建Command對象

conn.Open();//記得打開連接

try
{
SqlDataReader reader = cmd.ExecuteReader();//執行ExecuteReader

if (reader != null && reader.HasRows)
{
int rows = 0;//記錄行數
Console.WriteLine("**********Records of tb_SelCustomer**********\n");
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; ++i)
{
Console.WriteLine("{0}:{1}", reader.GetName(i), reader.GetValue(i));
}
++rows;
}
Console.WriteLine("\n共{0}行記錄", rows);
}
reader.Close();//關閉DataReader
}
catch (Exception ex)
{
Console.WriteLine("\nError:\n{0}", ex.Message);
}
}

Console.Read();
}
}
}

執行上面代碼后,我們可以看到在 場景(一) 中添加的數據。結果下圖所示。

 

(3)場景三:執行Select操作,返回單個值

      上面兩個場景相信大家都十分熟悉了。但是,當我們在操作數據庫時僅僅只需要返回一個值(比如返回行數),那該怎么辦呢?在此,我不得不承認Command對象確實人才濟濟,ExcuteScalar方法就是處理單個數據最優秀的人才。ExcuteScalar返回一個System.Object類型的數據,因此我們在獲取數據時需要進行強制類型轉換。當沒有數據時,ExcuteScalar方法返回System.DBNull。理論在於實踐,我們還是先看看一個實例吧!獲取tb_SelCustomer中的行數。代碼如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace Command3
{
class Program
{
static void Main(string[] args)
{
string connSQL = @"Data Source=.\SQLEXPRESS; Initial Catalog=db_MyDemo; Integrated Security=SSPI";
 
         
using (SqlConnection conn = new SqlConnection(connSQL))
{
string strSQL = "select count(*) from tb_SelCustomer";
SqlCommand cmd = new SqlCommand(strSQL, conn);//創建Command對象

try
{
conn.Open();//一定要注意打開連接
int rows = (int)cmd.ExecuteScalar();//執行命令
Console.WriteLine("執行ExcuteScalar方法:共{0}行記錄", rows);
}
catch (Exception ex)
{
Console.WriteLine("\nError:\n{0}", ex.Message);
}
}
            Console.Read();
}
}
}

 輸出結果如下:

 

 

7. 總結

       終於松一口氣了,歷時一個多星期,總算將Command對象一些最最基礎但又重要的知識點講完了。也不知道大家對Command對象了解了多少,不過我敢肯定的是,只要你認認真真看完本篇文章,至少對Command對象的一些基礎知識有印象了。歸根結底,Command對象就是一個載體。它向數據庫傳達了用戶的操作信息,而數據庫則通過Command對象向用戶返回處理結果。在下一篇文章中,我將講解Command對象的一些高級應用,希望大家能繼續關注和推薦。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM