天天看點

深入詳解DataTable

前言:ADO.NET概述

    在學習DataTable知識之前,我們有必要了解下ADO.NET。以下摘自MSDN:

ADO.NET 對 Microsoft SQL Server 和 XML 等資料源以及通過 OLE DB 和 XML 公開的資料源提供一緻的通路。資料共享使用者應用程式可以使用 ADO.NET 來連接配接到這些資料源,并檢索、處理和更新所包含的資料。

ADO.NET 通過資料處理将資料通路分解為多個可以單獨使用或一前一後使用的不連續元件。ADO.NET 包含用于連接配接到資料庫、執行指令和檢索結果的 .NET Framework 資料提供程式。您可以直接處理檢索到的結果,或将其放入 ADO.NET DataSet 對象,以便與來自多個源的資料或在層之間進行遠端處理的資料組合在一起,以特殊方式向使用者公開。ADO.NET DataSet 對象也可以獨立于 .NET Framework 資料提供程式使用,以管理應用程式本地的資料或源自 XML 的資料。

ADO.NET 類在 System.Data.dll 中,并且與 System.Xml.dll 中的 XML 類內建。當編譯使用 System.Data 命名空間的代碼時,請引用 System.Data.dll 和 System.Xml.dll。有關連接配接到資料庫、從資料庫中檢索資料并在指令提示中顯示該資料的 ADO.NET 應用程式示例,請參見 ADO.NET 示例應用程式。

ADO.NET 向編寫托管代碼的開發人員提供了類似于 ActiveX 資料對象 (ADO) 為本機元件對象子產品 (COM) 開發人員提供的功能。

ADO.NET中包含的對象及其關系如下圖:

<a target="_blank" href="http://blog.51cto.com/attachment/201105/222450735.gif"></a>

<a target="_blank" href="http://blog.51cto.com/attachment/201105/222522487.jpg"></a>

1、DataTable簡介

1.1 DataTable的定義

  表示記憶體中資料的一個表。 我們知道資料庫中存儲的是實體表,實體表中有一系列的資料。而DataTable即存儲在記憶體中的表,在持久化到資料庫之前,是不會對資料庫産生影響的,持久化到資料庫可以使用dataAdapter.Update的方法(dataAdapter是某個執行個體化的DataAdapter對象)。

注意:當通路 DataTable 對象時,請注意它們是按條件區分大小寫的。例如,如果一個 DataTable 被命名為“mydatatable”,另一個被命名為“Mydatatable”,則用于搜尋其中一個表的字元串被認為是區分大小寫的。但是,如果“mydatatable”存在而“Mydatatable”不存在,則認為該搜尋字元串不區分大小寫。

1.2 得到DataTable 

  得到DataTable有許多方法,下面簡單羅列出來:

1.2.1通過構造函數得到DataTable 

DataTable() 不帶參數初始化DataTable 類的新執行個體。 

DataTable(string tableName) 用指定的表名初始化DataTable 類的新執行個體。 

DataTable(string tableName, string tableNamespace) 用指定的表名和命名空間初始化DataTable 類的新執行個體。

1.2.2通過DataSet擷取DataTable

DataTable dt=ds.Tables["TableName"];//TableName是表名

1.2.3 通過DataRow自定義DataTable的結構

DataTable dt= new DataTable("TB_USER");

DataColumn colUserID = new DataColumn("USER_ID", Type.GetType("System.Int"));

dt.Columns.Add(colCurrency);

DataColumn colUserName= new DataColumn("USER_NAME", Type.GetType("System.String"));

dt.Columns.Add(colUserName);

這樣得到是一個表的結構,裡面沒有任何資料,表面為TB_USER。

1.2.4通過已有的DataTable得到新的DataTable

可以使用DataTable.Clone()方法獲得現有DataTable的表的結構,這在實際中也是常用的

1.2.5通過DataAdapter填充DataTable

DataAdapter.Fill(dt);來填充DataTable,這也是新手常用的方法,通常是些sql語句,然後使用command,是最基礎的方法。

1.2.6通過DataRow數組導入DataTable

DataRow [] drs;//drs是某個有資料的DataRow數組

foreach(DataRow dr in drs)

{

dt.ImportRow(dr);

}

1.3  DataTable常用屬性 

CaseSensitive 訓示表中的字元串比較是否區分大小寫。

ChildRelations 擷取此DataTable 的子關系的集合。

Columns 擷取屬于該表的列的集合。

Constraints 擷取由該表維護的限制的集合。

DefaultView 擷取可能包括篩選視圖或遊标位置的表的自定義視圖。

HasErrors 擷取一個值,該值訓示該表所屬的

DataSet 的任何表的任何行中是否有錯誤。

MinimumCapacity 擷取或設定該表最初的起始大小。該表中行的最初起始大小。預設值為 50。

Rows 擷取屬于該表的行的集合。

TableName 擷取或設定DataTable 的名稱。 

  DataSet中可包括多個 DataTable,可将多個查詢結構存到一個DataSet中,友善操作,而DataTable中又包括多個DataRow、DataColumn,可通過這些DataRow、DataColumn來檢視、操作其中的資料,而需将操作結果傳回給資料庫的話,則可以調用DataAdapter的 Update方法。

2、DataTable成員之DataRow

  DataTable是由一個個DataRow組合而成,DataTable.Rows[i]即表示其中的第i行。

  DataRow有一個十分重要的狀态(RowState),這個狀态經常被我們忽略,進而導緻一些莫名其妙的bug。RowState的值是一個枚舉類型的,RowState 有 Added, Modified, Unchanged, Deleted, Detached 幾種, 分别表示 DataRow 被添加, 修改, 無變化, 删除, 從表中脫離. 在調用一些方法或者進行某些操作之後, 這些狀态可以互相轉化。我們不做什麼判斷就開始操作DataRow,這就有可能導緻某些狀态為Deleted的行也同時被操作,這樣就有可能導緻髒資料的産生。

RowState 值

說明

Unchanged

自上次調用 AcceptChanges 之後,或自 DataAdapter.Fill 建立了行之後,未做出過任何更改。

Added

已将行添加到表中,但尚未調用 AcceptChanges。

Modified

已更改了行的某個元素。

Deleted

已将該行從表中删除,并且尚未調用 AcceptChanges。

Detached

該行不屬于任何 DataRowCollection。建立行的 RowState 設定為 Detached。通過調用 Add 方法将新的 DataRow 添加到 DataRowCollection 之後,RowState 屬性的值設定為 Added。

對于已經使用 Remove 方法(或是在使用 Delete 方法之後使用了 AcceptChanges方法)從 DataRowCollection 中移除的行,也設定為 Detached。

3、DataTable成員之DataColumn

 DataColumn 表示 DataTable 中列的架構。

3.1 DataColumn中常見的熟悉及其說明如下:

屬性名

Unique

設定DataColumn對象是否不允許重複的資料

Table 

DataColumn對象所屬的DataTable對象

ReadOnly

DataColumn對象是否隻讀

Ordinal

字段集合中的DataColumn對象順序

DefaultValue

  DataColumn對象的預設值

DataType

DataColumn對象資料類型

ColumnName

DataColumns集合對象中的字段名稱

Count 

DataTable對象中的字段數

Caption

DataColumn對象的标題

AutoIncrement

加入DataRow時,是否自動增加字段

AutoIncrementSeed

DataColumn對象的遞增種子

AllowDBNull

DataColumn對象是否接受Null值

3.2 DataColumn.Expression 表達式

擷取或設定表達式,用于篩選行、計算列中的值或建立聚合列。表達式的傳回類型由列的 DataType 來确定。Expression 屬性的一個用途是建立計算出的列。例如,若要計算稅值,就要将單價乘以特定地區的稅率。由于各地稅率不同,不可能将單一稅率放在一個列中;于是便用 Expression 屬性來計算這個值,如下面這一部分中的 Visual Basic 代碼所示:DataSet1.Tables("Products").Columns("tax").Expression = "UnitPrice * 0.086"第二個用途是建立聚合列。類似于計算出的值,聚合基于 DataTable 中的整個行集執行操作。一個簡單的示例就是計算該集中傳回的行數。這便是您将用來計算特定銷售人員所完成的交易數的方法,如下面的 Visual Basic 代碼所示:DataSet1.Tables("Orders").Columns("OrderCount").Expression = "Count(OrderID)";

在建立表達式時,使用 ColumnName 屬性來引用列。例如,如果一個列的 ColumnName 是“UnitPrice”,而另一個是“Quantity”,則表達式将是:

"UnitPrice * Quantity"

4、DataTable成員之DataView

DataView類似資料庫中的視圖。 

DataView 使您能夠建立 DataTable 中所存儲的資料的不同視圖,這種功能通常用于資料綁定應用程式。使用 DataView,您可以使用不同排序順序顯示表中的資料,并且可以按行狀态或基于篩選器表達式來篩選資料。

DataView 提供基礎 DataTable 中的資料的動态視圖:内容、排序和成員關系會實時反映其更改。此行為不同于 DataTable 的 Select 方法,後者從表中按特定的篩選器和/或排序順序傳回 DataRow 數組,雖然其内容反映對基礎表的更改,但其成員關系和排序卻則保持靜态。DataView 的動态功能使其成為資料綁定應用程式的理想選擇。

與資料庫視圖類似,DataView 為您提供了可向其應用不同排序和篩選條件的單個資料集的動态視圖。但是,與資料庫視圖不同的是,DataView 不能作為表來對待,無法提供聯接的表的視圖。另外,還不能排除存在于源表中的列,也不能追加不存在于源表中的列(如計算列)。

在實際運用中,我們時常使用如下代碼:

DataView dv = dt.DefaultView;

dv.Sort = "UserName"; //根據UserName排序,得到新的DataView

DataTable dtNew=dv.ToTable();//将DataView重新轉為DataTable

4.1 DataViewRowState: 

其實DataView是類似于DataTable,它裡面也有RowState,我們可以使用RowStateFilter來過濾不同狀态的行。

currentRows

包括所有未更新的、新的和修改的資料行

所有自上次調用AcceptChanges後删除的資料行

ModifiedCurrent

所有自上次調用AcceptChanges後修改過的資料行

ModifiedOriginal

所有自上次調用AcceptChanges後original版本的資料行

New

所有自上次調用AcceptChanges後新添加的行

OriginalRows

傳回初始資料行,包含unchanged和deleted 的

所有未更新的資料行

4.2 DataView的過濾器   

設定過濾 RowFilter是一個可讀寫的屬性,用來讀取和設定表過濾的表達式。public virtual string RowFilter {get; set;}

 你可以用列名,邏輯和數字運算符和常量的任意合法組合組成表達式。以下是一些例子:

dv.RowFilter = "Country = 'USA'";

dv.RowFilter = "EmployeeID &gt;5 AND Birthdate &lt; #1/31/82#"

dv.RowFilter = "Description LIKE '*product*'"

讓我們來看一下過濾器的基本規則和運算符。

過濾字元串是表達式的邏輯連接配接。可以用AND,OR,NOT來連接配接成一個較短的表達式,也可以使用圓括号來組成子句,指定優先的運算。

通常包含列名的子句同字母、數字、日期或另一個列名進行比較。這裡,可以使用關系運算符和算術運算符,如&gt;=, &lt;, &gt;, +, *, % (取模)等等。

如果要選取的行并不能友善地通過算術或邏輯運算符表達,你可以使用IN操作符。以下代碼顯示如何選取一個随機行:

dv.RowFilter = "employeeID IN (2,4,5)"

你也可以使用通配符*和%,它們同LIKE運算符一起使用時顯得更有用。它們都表示任意數量的字元,可以互相替代使用。

請注意,如果在LIKE子句中已經有了*或%字元,你必須用方括号将其括起,以免歧義。如果很不幸,字元串中方括号本身也存在了,那麼它也必須用将本身括起。這樣,比對語句會如下所示:

dv.RowFilter = "Description LIKE '[[]*[]]product[[]*[]]"

通配符隻允許在過濾字元串的開頭或結尾處使用,而不能在字元串中間出現。例如,下列語句會産生運作時錯誤:

dv.RowFilter = "Description LIKE 'prod*ct"

字元串必須以單引号括起,而日期型必須以#符号括起。字元型值可以使用小數點和科學計數法。

RowFilter也支援聚合函數,如SUM, COUNT, MIN,MAX, and AVG。如果表中沒有資料行,那麼函數将傳回NULL。

在介紹RowFilter表達式的最後,讓我們讨論三個很便利的函數:Len,IIF和Substring。

正如其名,Len()傳回特定表達式的長度。該表達式可以是一個列名,也可以是其他合法的表達式。

Substring()傳回指定的表達式自特定位置開始,特定長度的字元子串。

我最喜歡用的是IIF(),它按照邏輯表達式的值有一到兩個值。IIF是IF-THEN-ELSE語句的緊湊表達。文法如下:

IIF(expression, if_true, if_false)

通過該函數,可以建立非常複雜的過濾字元串。例如,假定你從SQL Server的Northwind資料庫中取得Employees表,下清單達式可以選出那些employeeID小于6且lastname為偶數個字元和employeeID大于6且lastname為奇數個字元的員工。

IIF(employeeID&lt;6, Len(lastname) %2 =0, Len(lastname) %2 &gt;0)

4.3 DataView 的排序 

DataView支援Sort屬性,可以用來對視圖中的内容排序。Sort由用逗号分隔的列名表達式進行排序。通過在任何列名後加ASC或者DESC限定詞,可以使得字段按照上升或者下降的順序排列。如果沒有方向限定詞,預設順序為ASC。

DataView是記憶體中的對象,是以排序在本地進行,無需調用資料庫伺服器。

執行個體篇 

執行個體1.DataTable分組統計資料

Name

Subject

Scores

Jack

001

90

002

85.5

Tom

78.5

Jerry

59

100

 如上表是dt中的資料,如果要分組進行統計各學生的平均科目成績,

可以使用如下的方法(當然如果你的.Net版本支援Linq的話,可以使用Linq)

思路:找出所有的學生,周遊表,計算該學生的平均成績,參考代碼如下:

//擷取所有的學生  

DataView myDataView = new DataView(dt);  

string[] strComuns ={ "Name"};  

DataTable dtTemp = myDataView.ToTable(true, strComuns);   

//建立DataTable存儲結構,結構同dt  

DataTable  dtNew=dt.Clone();   

//根據學生統計資料  

for (int i = 0; i &lt; dtTemp.Rows.Count; i++)  

{  

DataRow drDetail = dtNew.NewRow();  

drDetail["Name"] = dtTemp.Rows[i]["Name"].ToString();  

drDetail["Scores"] = dt.Compute("AVG(Scores)", "Name='" + dtTemp.Rows[i]["Name"].ToString() + "'");  

dtNew.Rows.Add(drDetail);  

 如果覺得好的話,請推薦;如果覺得十分好的話,請收藏,謝謝。 

    本文轉自xshf12345 51CTO部落格,原文連結:http://blog.51cto.com/alexis/573969,如需轉載請自行聯系原作者