1. 程式人生 > >asp.net夜話之七:ADO.NET介紹

asp.net夜話之七:ADO.NET介紹

《asp.net夜話》封面

Asp.net夜話之七:ADO.NET介紹
ADO.NET是對Microsoft ActiveX Data Objects (ADO)一個跨時代的改進,它提供了平臺互用性和可伸縮的資料訪問。由於傳送的資料都是XML格式的,因此任何能夠讀取XML格式的應用程式都可以進行資料處理。事實上,接受資料的元件不一定要是ADO .NET元件,它可以是基於一個Microsoft Visual Studio的解決方案,也可以是任何執行在其它平臺上的任何應用程式。
以前做資料庫訪問的時候,需要一直與資料庫保持連線,直到獲取完所有滿足需要的資料之後才會斷開資料庫連線,這種資料庫訪問方式稱之為連線式資料訪問技術。相比於以前的連線式資料訪問技術,ADO.NET除了提供連線式資料訪問技術之外,還提供了另一種斷開式解決方案,那就是在記憶體中模擬一個數據庫,也就是記憶體中的資料庫。
我們知道在實際的資料庫技術中,每個資料庫就是一個業務邏輯單元,一般來說這個資料庫包含了實現一個應用軟體或者一個網站所需要的全部資料。在這裡資料庫就是頂級物件,我們引用建立資料庫時所用到的名詞database來表示(因為建立資料庫的SQL語句是create database),在一個數據庫裡可以包含有多個表(table)和檢視(view),除此之外還可以包含有一些外來鍵關係等。在一個表(table)或者檢視(view)裡可以包含多個列(column)和行(row)。
在ADO.NET中對上面提到的物件都在記憶體中進行了模擬,在記憶體中的資料庫物件稱之為DataSet,一個記憶體中的資料庫(DataSet)可以包含多個在記憶體中的表(DataTable)和記憶體中的檢視(DataView),並且也允許在表存在一些關係(DataRelation)。同時在一個記憶體中的表(DataTable)或者記憶體中的檢視(DataView)中也允許存在行(DataRow)和列(DataColumn)。
物理資料庫與記憶體資料庫之間的各物件的對應關係如下:
 


在上圖中顏色相同的表示二者基本上是一種對應關係。

在本篇將講述6個ADO.NET中的常用物件:
Connection物件
Command物件
DataReader物件
DataAdapter物件
DataSet物件
DataTable物件
DataRow物件
DataColumn物件
引數化SQL語句
分頁查詢SQL語句

嚴格地說,在.net類庫中並沒有Connection、Command、DataAdapter和DataReader物件的,這是對相關的物件做了一個抽象。在實際的開發中,我們經常用到的資料庫有Access、SQL Server、Oracle、MySQL等,儘管大部分都遵循SQL國際化標準,但是它們在遵循標準的前提下又做了一些擴充,並且即使遵循了相同的標準,但是實現方法並不相同,所以在某些情況下實現相同的功能可能在不同的資料庫中SQL語句並不相同。
於是,在ADO.NET也定義了一套用於訪問資料庫的標準,當然這個標準是以介面(interface)的形式提供的,各資料庫廠商只要實現了這個介面就能在ADO.NET下正常工作(這也是介面的作用,介面就是用於指定規範,自己本身並不實現,在Java中針對資料庫訪問也有一套介面留待各資料庫來實現)。當然在.net類庫中微軟已經提供對Access、SQL Server和Oracle資料庫對上面提到的介面的實現。
在ADO.NET中定義的這一套介面是IDbConnection、IDbCommand、IDbDataAdapter和IDataReader,並且還有一套實現這些介面的抽象類,分別是DbConnection、DbCommand、DbDataAdapter和DataReader。

 
上圖最上面的是資料庫訪問介面,緊接著的是資料庫訪問抽象類,下面是針對不同資料庫中實現這些介面的類,並且在括號中註明了其所在的名稱空間,比如針對MySQL資料的資料庫訪問類就位於MySql.Data.MySqlClient名稱空間下,關於MySql的資料庫訪問類需要到MySql資料庫的官方網站去下載,它的官方網站是http://www.mysql.com。其它的資料庫訪問類都在.net類庫中自帶了。
注意:訪問SQL Server7.0以下版本的SQL Server資料庫時需要用System.Data.OleDb名稱空間下一套資料庫訪問類,雖然這一套資料庫訪問類同樣也能訪問SQL Server2000以上版本,但是沒有辦法利用SQL Server資料庫的一些新特性,所以不建議使用System.Data.OleDb名稱空間下的類訪問SQL Server2000以上的版本。
在本篇的講述中,針對SQL Server資料庫講述Connection、Command、DataAdapter和DataReader物件的用法,它們在其它資料庫中也有對應的類,除了有些SQL語句語法不一樣之外,用法是基本一樣的。

Connection物件
Connection物件也稱為資料庫連線物件,Connection物件的功能是負責對資料來源的連線。所有Connection物件的基類都是DbConnection類。
Connection物件有兩個重要屬性:
ConnectionString:表示用於開啟 SQL Server 資料庫的字串;
State:表示 Connection 的狀態,有Closed和Open兩種狀態。
Connection物件有兩個重要方法:
Open()方法:指示開啟資料庫;
Close()方法:指示關閉資料庫。
在實際開發中很多朋友經常詢問資料庫連線字串該怎麼寫,其實有一個很簡單的技巧,我們可以在Visual Studio 2005工具箱中找到資料分組,如下圖:
 
開啟或新建一個asp.net頁面,在設計檢視下雙擊SqlDataSource控制元件就會新增一個SqlDataSource到當前頁面,如下圖:
 
當我們用滑鼠單擊SqlDataSouce控制元件時會出現一個小三角箭頭,如上圖所示,當我們點選這個三角箭頭時會出現如下圖所示的介面:
 
點選“配置資料來源”時會出現下面的介面:
 
點“新建連線”後出現如下介面:
 
在這個介面中預設是連線到SQL Server資料庫,其實我們還可以利用這個嚮導連線到其它資料庫的,我們點選“資料來源”旁邊的“更改”按鈕出現如下圖所示的介面:
 
從上面的介面中我們可以看出可以利用這個連線嚮導配置連線到Access資料庫檔案、ODBC資料來源、SQL Server資料庫、SQL Server手機版資料庫、SQL Server資料庫檔案、Oracle資料庫檔案及其它資料庫。
在這裡我們選擇Microsoft SQL Server選項,連線到SQL Server資料庫。如果我們在區域網中,我們可以點選“新增連線”介面中的重新整理按鈕來檢視區域網中有哪些SQL Server資料庫可以連線。連線到資料庫可以用下面的方式:
(1)如果要連線的資料庫伺服器與開發者的機器在同一個局域網裡,可以使用區域網IP地址或者區域網中的電腦主機名;
(2)如果要連線的資料庫伺服器與開發者的機器不在同一個區域網內,那麼就要求資料庫伺服器必須有一個公網IP,我們可以使用公網IP來連線,如果資料庫伺服器還有網際網路域名,那麼用網際網路域名也是可以的。
(3)如果要連線的資料庫伺服器與開發者所使用的機器是同一臺機器,那麼可以使用以下幾種方式之一:”(local)”或者”.”或者”127.0.0.1”。
需要注意的是,如果在一臺機器上執行者同一種資料庫的不同版本,比如說在”zhoufoxcn”這臺主機上同時執行著SQL 2000、SQL 2005和SQL Express三種版本,並且它們所使用的Windows服務名分別為”SQL2000”、”SQL2005”和”SQLExpress”,那麼我們要連線到SQL 2000這個資料庫上所使用的伺服器名就應該填寫”zhoufoxcn/SQL2000”這種“主機名/例項名”的方式或者“主機IP/例項名”,這種情況在同時安裝了Visual Studio 2005和SQL 2005的朋友那裡很常見,因為SQL Express是針對學生的功能有限的免費版本,這個版本的資料庫在安裝Visual Studio 2005時預設是一同安裝的。
在上面的“新增連線”視窗,我們分別填寫如下資訊:
 
在上面我們連線的是本機上的資料庫,所使用的資料庫帳號是sa,訪問的資料庫是AspNetStudy,建立這個資料的SQL指令碼如下:

  1. IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = N'AspNetStudy')
  2.  DROP DATABASE [AspNetStudy]
  3. GO
  4. CREATE DATABASE [AspNetStudy]  ON (NAME = N'AspNetStudy_Data', FILENAME = N'C:/Program Files/Microsoft SQL Server/MSSQL/data/AspNetStudy_Data.MDF' , SIZE = 1, FILEGROWTH = 10%) LOG ON (NAME = N'AspNetStudy_Log', FILENAME = N'C:/Program Files/Microsoft SQL Server/MSSQL/data/AspNetStudy_Log.LDF' , SIZE = 1, FILEGROWTH = 10%)
  5.  COLLATE Chinese_PRC_CI_AS
  6. GO
  7. use [AspNetStudy]
  8. GO
  9. if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[UserInfo]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
  10. drop table [dbo].[UserInfo]
  11. GO
  12. CREATE TABLE [dbo].[UserInfo] (
  13.  [UserID] [int] IDENTITY (1, 1) NOT NULL ,
  14.  [UserName] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
  15.  [RealName] [nvarchar] (8) COLLATE Chinese_PRC_CI_AS NOT NULL ,
  16.  [Age] [tinyint] NOT NULL ,
  17.  [Sex] [bit] NOT NULL ,
  18.  [Mobile] [char] (11) COLLATE Chinese_PRC_CI_AS NULL ,
  19.  [Phone] [char] (11) COLLATE Chinese_PRC_CI_AS NULL ,
  20.  [Email] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL 
  21. ) ON [PRIMARY]
  22. GO
  23.  CREATE  UNIQUE  INDEX [IX_UserName] ON [dbo].[UserInfo]([UserName]) WITH  IGNORE_DUP_KEY  ON [PRIMARY]
  24. GO
  25. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('zhangfei','張飛',36,'13455663420','03517890360','[email protected]',1);
  26. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('guanyu','關羽',38,'13455663421','03517890361','[email protected]',1);
  27. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('liubei','劉備',42,'13455663422','03517890362','[email protected]',1);
  28. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('zhougong','周公',29,'13455663423','03517890363','[email protected]',1);
  29. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('zhaoyun','趙雲',32,'13455663424','03517890364','[email protected]',1);
  30. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('huanggai','黃蓋',50,'13455663425','03517890365','[email protected]',1);
  31. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('zhugeliang','諸葛亮',27,'13455663426','03517890366','[email protected]',1);
  32. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('jiangwei','姜維',22,'13455663427','03517890367','[email protected]',1);
  33. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('caocao','曹操',48,'13455663428','03517890368','[email protected]',1);
  34. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('guojia','郭嘉',32,'13455663429','03517890369','[email protected]',1);
  35. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('sunquan','孫權',33,'13455663430','03517890370','[email protected]',1);
  36. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('diaochan','貂禪',20,'13455663431','03517890371','[email protected]',0);
  37. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('yangyuhuan','楊玉環',24,'13455663432','03517890372','[email protected]',0);
  38. insert into UserInfo([UserName],[RealName],[Age],[Mobile],[Phone],[Email],[Sex])values('wangzhaojun','王昭君',26,'13455663433','03517890373','[email protected]',0);
  39. go


我們可以點選一下“測試連線”按鈕,如果彈出連線成功的提示訊息就表示這個資料庫連線是可用的。點選“確定”按鈕,回到“配置資料來源”介面,這時候點選連線字串旁邊的”+”按鈕就可以看到資料庫的連線字串資訊,如下圖所示:
 
把這個字串拷貝到我們需要例項化Connection物件的地方,可以作為建構函式的引數例項化一個SqlConnection物件。
由於這個例子前後臺程式碼都比較簡單,所以在Visual Studio 2005建立的單頁模式網頁(程式碼和頁面都在一個頁面裡),下面是程式碼:

  1. <%@ Page Language="C#" %>
  2. <%@ Import Namespace="System.Data.SqlClient" %>
  3. <%@ Import Namespace="System.Data" %>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  5. <scriptrunat="server">
  6.     protected void Page_Load(object sender, EventArgs e)
  7.     {
  8.         SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=AspNetStudy;Persist Security Info=True;User ID=sa;Password=sa");
  9.         //注意,DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")是將當前時間格式化為類似於2008-10-09 00:00:03的形式的字串
  10.         Response.Write("時間"+ DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")+"當前資料庫連線狀態是:"+connection.State +"<br/>");
  11.         connection.Open();
  12.         Response.Write("時間" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "當前資料庫連線狀態是:" + connection.State + "<br/>");
  13.         connection.Close();
  14.         Response.Write("時間" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "當前資料庫連線狀態是:" + connection.State + "<br/>");
  15.     }
  16. </script>
  17. <htmlxmlns="http://www.w3.org/1999/xhtml">
  18. <headrunat="server">
  19. <title>無標題頁</title>
  20. </head>
  21. <body>
  22. <formid="form1"runat="server">
  23. <div>
  24. </div>
  25. </form>
  26. </body>
  27. </html>

以下是執行效果:
 
可見例項化一個Connection物件的時候,被例項化的Connection物件是關閉的,我們需要Open這個Connection物件,執行完畢相關操作之後再關閉這個Connection物件。

Command物件
Command物件也稱為資料庫命令物件,Command物件主要執行包括新增、刪除、修改及查詢資料的操作的命令。也可以用來執行儲存過程。用於執行儲存過程時需要將Command物件的CommandType 屬性設定為CommandType.StoredProcedure,預設情況下CommandType 屬性為CommandType.Text,表示執行的是普通SQL語句。
Command主要有三個方法:
ExecuteNonQuery () :執行一個SQL語句,返回受影響的行數,這個方法主要用於執行對資料庫執行增加、更新、刪除操作注意查詢的時候不是呼叫這個方法
ExecuteReader ():執行一個查詢的SQL語句,返回一個DataReader物件。
ExecuteScalar ():從資料庫檢索單個值。這個方法主要用於統計操作。

有關ExecuteNonQuery ()和ExecuteReader ()的用法在稍後馬上提到,這裡我主要演示ExecuteScalar ()這個方法的用法。
請看下面的例子:
 
我們可以看到上面的SQL語句執行的結果是一行一列的結果集,ExecuteScalar ()這個方法就是針對這種情況的,這個方法只返回查詢結果集的第一行第一列。
同樣,因為這個頁面的程式碼和設計部分非常簡單,仍然採用的單頁模式,程式碼如下:

  1. <%@ Page Language="C#" %>
  2. <%@ Import Namespace="System.Data.SqlClient" %>
  3. <%@ Import Namespace="System.Data" %>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  5. <scriptrunat="server">
  6.     protected void Page_Load(object sender, EventArgs e)
  7.     {
  8.         //例項化Connection物件
  9.         SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=AspNetStudy;Persist Security Info=True;User ID=sa;Password=sa");
  10.         //例項化Command物件
  11.         SqlCommand command = new SqlCommand("select count(1) as 男性人數 from UserInfo where sex=1", connection);
  12.         //開啟Connection物件
  13.         connection.Open();
  14.         //執行SQL語句
  15.         int count = int.Parse(command.ExecuteScalar().ToString());
  16.         //關閉Connection物件
  17.         connection.Close();
  18.         Response.Write("在UserInfo表裡共有" + count + "個男性。");
  19.     }
  20. </script>
  21. <htmlxmlns="http://www.w3.org/1999/xhtml">
  22. <headrunat="server">
  23. <title>無標題頁</title>
  24. </head>
  25. <body>
  26. <formid="form1"runat="server">
  27. <div>
  28. </div>
  29. </form>
  30. </body>
  31. </html>

這個頁面執行的結果如下:
 
在操作資料庫的時候,為了提高效能,都遵循一個原則:資料庫連線物件應該儘可能晚開啟,儘可能早關閉。在上面的例子中,在Command物件需要執行資料庫操作之前才打開資料庫連線物件,執行資料庫操作之後馬上就關閉了資料庫連線物件。希望初學者們記住這個原則。


DataReader物件
DataReader物件是一個讀取行的只讀流的方式,繫結資料時比使用資料集方式效能要高,因為它是隻讀的,所以如果要對資料庫中的資料進行修改就需要藉助其它方法將所作的更改儲存到資料庫。
DataReader物件不能通過直接例項化,必須藉助與相關的Command物件來建立例項,例如用SqlCommand的例項的ExecuteReader()方法可以建立SqlDataReader例項。
因為DataReader物件讀取資料時需要與資料庫保持連線,所以在使用完DataReader物件讀取完資料之後應該立即呼叫它的Close()方法關閉,並且還應該關閉與之相關的Connection物件。在.net類庫中提供了一種方法,在關閉DataReader物件的同時自動關閉掉與之相關的Connection物件,使用這種方法是可以為ExecuteReader()方法指定一個引數,如:
SqlDataReader reader =command.ExecuteReader(CommandBehavior.CloseConnection);
CommandBehavior是一個列舉,上面使用了CommandBehavior列舉的CloseConnection值,它能在關閉SqlDataReader時關閉相應的SqlConnection物件。
並且DataReader物件讀取資料有三種方式:
一種是按查詢的時候列的索引用指定的方式來讀取列值,無需做相應轉換,如GetByte(int i)就是讀取第i列的值並且轉換成byte型別的值。第這種方法的優點是指定列後直接將該列的直接讀取出來了,無需再轉換,缺點是一旦指定的列不能按照指定的方式轉換時就會丟擲異常,比如資料庫裡欄位的型別是string型別或者該欄位的值為空時按照GetByte(i)這種方式讀取會丟擲異常。
第二種方式就是按照列索引的方式讀取,在讀取的時候並不進行值轉換,如:reader[5]就是讀取第5列的值(這裡reader是一個Reader物件的例項),這樣得到的值是一個object型別的值,這也很好理解,因為在資料庫可能儲存各種型別的值,而object是所有類的基類,所以這個方法不會丟擲異常。如果要得到它的正確型別,還需要根據資料庫裡的欄位進行進行相應轉換。
最後一種是按照列名的方式去讀,並且在讀的時候也不進行相應轉換,得到的是object型別的值。
綜合前面三種方式各有特點,第一種方式最直接,但是有可能丟擲異常,第二種方式比第一種稍微靈活一些,我們可以根據讀取到值為空(在.net裡用DBNull類來表示,可以表示資料庫中任意資料型別的空值),我們就不進行相應的型別轉換,避免出現異常。第三種方式按照列的名字來讀取資料,也需要按照第二種方式進行一定的轉換。就效能來說第一種最高,第二種稍低,第三種最低(這很好理解,假設要在一個旅館裡找人直通過房間號找肯定比通過名字找快),就靈活性來說第三種最靈活,第二種次之,第一種最不靈活(假如在後來編寫SQL語句中更改了列的索引,第一種和第二種都可能出現問題)。實際開發中根據實際情況選擇合適的方式。
下面是一個使用DataReader物件讀取資料的例子,因為程式碼不是很多並且也不復雜,所以採用了單頁模式,並且還演示了三種讀取資料的方式,程式碼如下:

  1. <%@ Page Language="C#" %>
  2. <%@ Import Namespace="System.Data.SqlClient" %>
  3. <%@ Import Namespace="System.Data" %>
  4. <%@ Import Namespace="System.Text" %>
  5. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  6. <scriptrunat="server">
  7. //注:為了方便沒有使用程式碼頁面方式,實際開發中這種做大很少見
  8.     protected void Page_Load(object sender, EventArgs e)
  9.     {
  10.     }
  11.     public void ShowData()
  12.     {
  13.         //例項化Connection物件
  14.         SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=AspNetStudy;Persist Security Info=True;User ID=sa;Password=sa");
  15.         //例項化Command物件
  16.         SqlCommand command = new SqlCommand("select * from UserInfo where sex=1", connection);
  17.         //開啟Connection物件
  18.         connection.Open();
  19.         //得到DataReader的例項,注意使用了CommandBehavior這個引數,以便同時關閉Connection
  20.         SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
  21.         //如果當前記錄還有下一條記錄,則迴圈不會終止
  22.         while (reader.Read())
  23.         {
  24.             Response.Write("<tr><td>" + reader.GetInt32(0) + "</td>");//按照列順序和對應型別直接讀取值
  25.             Response.Write("<td>" + reader.GetString(1) + "</td>");//按照列順序和對應型別直接讀取值
  26.             Response.Write("<td>" + reader.GetString(2) + "</td>");//按照列順序和對應型別直接讀取值
  27.             Response.Write("<td>" + reader.GetByte(3) + "</td>");//按照列順序和對應型別直接讀取值
  28.             //下面是按照列順序直接讀取值,並且根據值來判斷最終顯示結果
  29.             Response.Write("<td>" + (reader.GetBoolean(4)==true?"男":"女") + "</td>");
  30.             //根據列順序讀,列的值需要做相應轉換
  31.             Response.Write("<td>" + reader[5].ToString() + "</td>");
  32.             //根據列名來讀取,列的值需要做相應轉換
  33.             Response.Write("<td>" + reader["Phone"] + "</td>");
  34.             Response.Write("<td>" + reader["Email"].ToString() + "</td></tr>/n");
  35.         }
  36.         reader.Close();
  37.     }
  38. </script>
  39. <htmlxmlns="http://www.w3.org/1999/xhtml">
  40. <headrunat="server">
  41. <title>無標題頁</title>
  42. </head>
  43. <body>
  44. <formid="form1"runat="server">
  45. <div>
  46. <tableborder="1"cellpadding="0"cellspacing="0">
  47. <tr><td>編號</td><td>帳號</td><td>真實姓名</td><td>年齡</td><td>性別</td><td>手機</td><td>電話</td><td>電子郵件</td></tr>
  48. <
  49.         //在頁面中呼叫後臺程式碼,這樣也能保證生成的程式碼不會位於<html></html>標記之外
  50.         ShowData(); 
  51.     %>
  52. </table>
  53. </div>
  54. </form>
  55. </body>
  56. </html>

下面是執行結果:
 

DataAdapter物件
DataAdapter物件也稱之為資料介面卡物件,DataAdapter物件利用資料庫連線物件(Connection)連線的資料來源,使用資料庫命令物件(Command)規定的操作從資料來源中檢索出資料送往資料集物件(DataSet),或者將資料集中經過編輯後的資料送回資料來源。
資料介面卡將資料填入資料集時呼叫方法Fill(),語句如下:

  1. dataAdapter1.Fill (dataTable);//直接填充表

  或者

  1. dataAdapter1.Fill (dataSet11, "Products");//填充dataSet11資料集中的"Products"表

當dataAdapter1呼叫Fill() 方法時將使用與之相關聯的命令元件所指定的 SELECT 語句從資料來源中檢索行。然後將行中的資料新增到 DataSet 中的DataTable 物件中或者直接填充到DataTable的例項中,如果 DataTable 物件不存在,則自動建立該物件。
當執行上述SELECT語句時,與資料庫的連線必須有效,但不需要用語句將連線物件開啟。如果呼叫Fill()方法之前與資料庫的連線已經關閉,則將自動開啟它以檢索資料,執行完畢後再自動將其關閉。如果呼叫Fill()方法之前連線物件已經開啟,則檢索後繼續保持開啟狀態。
注意:一個數據集中可以放置多張資料表。但是每個資料介面卡只能夠對應於一張資料表。

DataSet物件
DataSet物件也稱為資料集物件,DataSet物件用於表示那些儲存在記憶體中的資料,它相當於一個記憶體中的資料庫。它可以包括多個DataTable物件及DataView物件。DataSet主要用於管理儲存在記憶體中的資料以及對資料的斷開操作。
由於DataSet物件提供了一個離線的資料來源,這樣減輕了資料庫以及網路的負擔,在設計程式的時候可以將DataSet物件作為程式的資料來源。
下面是一個利用Adapter物件填充資料到DataTable(或DataSet)並顯示的例子,這個例子採用了頁面和程式碼分離模式,前臺程式碼如下:

  1. <%@ Page Language="C#"AutoEventWireup="true"CodeFile="DataAdapter.aspx.cs"Inherits="DataAdapter" %>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <htmlxmlns="http://www.w3.org/1999/xhtml">
  4. <headrunat="server">
  5. <title>利用Adapter物件填充DataTable的例子</title>
  6. </head>
  7. <body>
  8. <formid="form1"runat="server">
  9. <div>
  10. <tableborder="1"cellpadding="0"cellspacing="0">
  11. <tr><td>編號</td><td>帳號</td><td>真實姓名</td><td>年齡</td><td>性別</td><td>手機</td><td>電話</td><td>電子郵件</td></tr>
  12. <
  13.         //在頁面中呼叫後臺程式碼,這樣也能保證生成的程式碼不會位於<html></html>標記之外
  14.         ShowData(); 
  15.     %>
  16. </table>
  17. </div>
  18. </form>
  19. </body>
  20. </html>

相應的後臺程式碼:

  1. using System;
  2. using System.Data;
  3. using System.Configuration;
  4. using System.Collections;
  5. using System.Web;
  6. using System.Web.Security;
  7. using System.Web.UI;
  8. using System.Web.UI.WebControls;
  9. using System.Web.UI.WebControls.WebParts;
  10. using System.Web.UI.HtmlControls;
  11. using System.Data.SqlClient;
  12. public partial class DataAdapter : System.Web.UI.Page
  13. {
  14. protectedvoid Page_Load(object sender, EventArgs e)
  15.     {
  16.     }
  17. //供前臺頁面呼叫的方法,這個方法必須是protected或者public
  18. protectedvoid ShowData()
  19.     {
  20. //例項化Connection物件
  21.         SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=AspNetStudy;Persist Security Info=True;User ID=sa;Password=sa");
  22. //例項化Command物件
  23.         SqlCommand command = new SqlCommand("select * from UserInfo where sex=0", connection);
  24.         SqlDataAdapter adapter = new SqlDataAdapter(command);
  25. /*
  26.          下面的被註釋掉的程式碼與上面的程式碼是等效的
  27.         SqlDataAdapter adapter = new SqlDataAdapter("select * from UserInfo where sex=0", connection);
  28.          */
  29.         DataTable data = new DataTable();
  30.         adapter.Fill(data);
  31. /* 下面的被註釋掉語句與上面填充DataTable的效果是一樣的,我更傾向於沒有註釋掉的部分
  32.         DataSet ds = new DataSet();//例項化DataSet
  33.         adapter.Fill(ds, "UserInfo");//填充ds中的"UserInfo"表
  34.         DataTable data = ds.Tables["UserInfo"];
  35.         */
  36. for (int i = 0; i < data.Rows.Count; i++)
  37.         {
  38.             Response.Write("<tr><td>" + data.Rows[i]["UserId"].ToString() + "</td>");
  39.             Response.Write("<td>" + data.Rows[i]["UserName"].ToString() + "</td>");
  40.             Response.Write("<td>" + data.Rows[i]["RealName"].ToString() + "</td>");
  41.             Response.Write("<td>" + data.Rows[i]["Age"].ToString() + "</td>");
  42. //下面是按照列順序直接讀取值,並且根據值來判斷最終顯示結果
  43.             Response.Write("<td>" + (bool.Parse(data.Rows[i]["Sex"].ToString()) == true ? "男" : "女") + "</td>");
  44. //根據列順序讀,列的值需要做相應轉換
  45.             Response.Write("<td>" + data.Rows[i]["Mobile"].ToString() + "</td>");
  46. //根據列名來讀取,列的值需要做相應轉換
  47.             Response.Write("<td>" + data.Rows[i]["Phone"].ToString() + "</td>");
  48.             Response.Write("<td>" + data.Rows[i]["Email"].ToString() + "</td></tr>/n");
  49.         }
  50.     }
  51. }

上面的程式程式碼基本與使用DataReader物件的例子相同,不過這裡查詢的所有女性使用者,效果如下:
 

DataTable物件
DataTable 是 ADO.NET 庫中的核心物件,就像普通的資料庫中的表一樣,它也有行和列。它主要包括DataRow和DataColumn,分別代表行和列。
(1) 資料行(DataRow)
資料行是給定資料表中的一行資料,或者說是資料表中的一條記錄。它可能代表一個學生、一位使用者、一張訂單或者一件貨物的相關資料。DataRow物件的方法提供了對錶中資料的插入、刪除、更新和檢視等功能。提取資料表中的行的語句如下:
DataRow dr = dt.Rows[n];
其中:DataRow代表資料行類;dr是資料行物件;dt代表資料表物件; n代表行的序號(序號從0開始)。
(2) 資料列(DataColumn)
資料表中的資料列(又稱欄位)定義了表的資料結構,例如,可以用它確定列中的資料型別和大小,還可以對其他屬性進行設定。例如,確定列中的資料是否是隻讀的、是否是主鍵、是否允許空值等;還可以讓列在一個初始值的基礎上自動增殖,增值的步長還可以自行定義。
 某列的值需要在資料行的基礎上進行。語句如下:

  1. string dc = dr.Columns["欄位名"].ToString();

  或者 

  1. string dc = dr.Column[i].ToString();//i表示對應的列索引

 綜合前面的語句,若想取出資料表(dt)中第3條記錄中的“姓名”欄位,並將該欄位的值放入一輸入框(textBox1)中時,語句可以寫成:

  1. DataRow dRow =