1. 程式人生 > >C# 資料操作系列 - 3. ADO.NET 離線查詢

C# 資料操作系列 - 3. ADO.NET 離線查詢

# 0. 前言 在上一篇中,我故意留下了查詢的示範沒講。雖然說可以通過以下程式碼獲取一個DataReader: ```c# IDataReader reader = command.ExecuteReader(); ``` 然後通過reader一行一行的讀取資料,但是我並不推薦這樣使用。 在查詢這一高頻需求上,C#為之做了很多工作,提供了更多的選擇。這裡介紹一個查詢的另一套寫法。 # 1. 離線查詢 C#在查詢上提供了另一種機制,可以一次性從資料庫把結果讀取到網路快取區中,直到使用的時候才載入到程式中。 在離線查詢裡最關鍵的三個介面或類: - IDataAdapter 一種介面卡,用來獲取資料並填充或更新DataSet - DataSet 表示資料在記憶體中的快取 - DataTable 表示記憶體中一個數據表 IDataAdapter用來提供資料,DataSet表示adapter讀取的結果集,其中有一個DataTable集合表示執行的SQL查詢結果。至於為什麼是集合,是因為IDataAdapter允許執行多條查詢語句。 好,讓我們粗略瀏覽一下這個三個關鍵點的屬性和方法: IDataAdapter: ```c# public int Fill (System.Data.DataSet dataSet);//將查詢出來的結果填充到DataSet裡 ``` 在C#內部,其實不允許推薦直接繼承該介面,推薦繼承DataAdapter類,該類規定了資料庫Adapter在初始化的時候,必須提供一個可以訪問的資料庫連線和要執行的命令文字。 當然其部分實現類允許以屬性的形式後賦值這兩個關鍵內容。 DataSet: ```c# public DataSet (); public DataSet (string dataSetName);//指定資料集的名稱 public System.Data.DataTableCollection Tables { get; }//獲取包含在 DataSet 中的表的集合 ``` DataSet有很多有用的方法,但是在今天我們只用關係這些就可以了。 其中Tables 引入了一個沒有提到的型別,DataTableCollection。那麼我們可以順藤摸瓜,來看看裡面有什麼關鍵的內容: ```c# public System.Data.DataTable this[int index] { get; }// 獲取指定下標的DataTable public System.Data.DataTable this[string name] { get; }//獲取具有指定名稱的DataTable ``` 可以看到提供了一種我們可以獲取到裡面的DataTable元素的索引訪問方式。 DataTable : ```c# public System.Data.DataSet DataSet { get; }//獲取此表所屬的 DataSet。 public System.Data.DataColumnCollection Columns { get; }//獲取屬於該表的列的集合 public System.Data.DataRowCollection Rows { get; }//獲取屬於該表的行的集合 ``` 又出現了兩個新的類:DataColumnCollection、DataRowCollection。這是一種內部集合的實現類,功能類似於List,但又不等同於List。 我們大概看一下對我們有用的屬性和方法: DataColumnCollection: ```c# public virtual int Count { get; }//獲取集合中的元素總數 public System.Data.DataColumn this[int index] { get; }//從集合中獲取位於指定索引位置的 DataColumn public System.Data.DataColumn this[string name] { get; }//從具有指定名稱的集合中獲取 DataColumn。 ``` DataRowCollection: ```c# public override int Count { get; } public System.Data.DataRow this[int index] { get; }// 獲取索引處的行 ``` 嗯,好先到此為止。調轉方向回到上個路口,重新來。讓我們看看DataColumn和DataRow又有哪些值得我們現在關注的: DataColumn: ```c# public string ColumnName { get; set; }//獲取或設定 DataColumnCollection 中的列的名稱 public Type DataType { get; set; }//獲取或設定儲存在列中的資料的型別 ``` DataRow: ```c# public object this[System.Data.DataColumn column] { get; set; }//獲取或設定指定 DataColumn 中儲存的資料 public object this[int columnIndex] { get; set; }//獲取或設定由索引指定的列中儲存的資料 public object this[string columnName] { get; set; }//獲取或設定由名稱指定的列中儲存的資料 public object[] ItemArray { get; set; }//通過陣列獲取或設定此行的所有值 ``` 到目前為止,離線查詢的支援類和介面就介紹了個大概。那麼我們看看如何進行一個離線查詢吧 # 2.實踐看看 以SQL Server資料庫為例: 獲取一個SqlDataAdapter,C#提供了四種方式獲取: ```c# public SqlDataAdapter ();//構造一個沒有連線和命令的Adapter物件 public SqlDataAdapter (System.Data.SqlClient.SqlCommand selectCommand);// 指定一個查詢命令 public SqlDataAdapter (string selectCommandText, System.Data.SqlClient.SqlConnection selectConnection);//指定查詢命令,和連線 public SqlDataAdapter (string selectCommandText, string selectConnectionString);//指定查詢命令和連線字串 ``` 引用名稱空間: ```c# using System.Data; using System.Data.SqlClient; ``` 那麼,我們先構造一個Adapter: ```c# var connectStr = "Data Source=.;Initial Catalog=Old;Integrated Security=True"; var sql = "select * from Area_PostCode"; var adapter = new SqlDataAdapter(sql, connectStr); ``` 然後建立一個用於儲存資料的DataSet,並把資料填充進去: ```c# DataSet set = new DataSet(); adapter.Fill(set); ``` 然後可以看到這個set中的資料應該是這樣的: ![image-20200512004118597](https://img2020.cnblogs.com/other/1266612/202005/1266612-20200512094240835-2078820951.png) > 上圖是在VS中的除錯模式中,可以看到 根據上圖我們大概可以猜測一下DataTable內部的資料結構,或者C#讓我們理解的結構是什麼。 其中DataColumn對應著圖中列,ColumnName就是圖 所示的列名。而DataRow就是行,ItemArray則是一行行資料。 這樣一來,顯然就比直接使用IDataReader訪問資料要方便很多。 依據上例: 我們試著獲取一下第三行的Province列值,如果覺得這個表述彆扭的話,看一下我的寫法,就知道我為什麼這麼表示了。 ```c# var table = set.Tables[0];// 先拿到第一個表 var value = table.Rows[2]["Province"]; ``` 這是一種螞蟻搬家式的讀取資料方式。C#為DataTable提供了一個擴充套件方法: ```c# public static EnumerableRowCollection