深入詳解DataTable


在學習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中包含的對象及其關系如下圖:

 

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);

}

 

代碼 

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->   DataTable dt = new DataTable();
            
            dt.Columns.Add("id", typeof(int));

            dt.Rows.Add(new Object[] { 1 });

            DataTable dt2 = new DataTable();

            dt2=dt.Clone();

            foreach (DataRow dr in dt.Rows)
            {
                dt2.ImportRow(dr);
            }

            foreach (DataRow item in dt2.Rows)
            {
                Response.Write(item["id"]);
            }

1.3  DataTable常用屬性 


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

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

Columns 獲取屬於該表的列的集合。

Constraints 獲取由該表維護的約束的集合。

DefaultView 獲取可能包括篩選視圖或游標位置的表的自定義視圖。

HasErrors 獲取一個值,該值指示該表所屬的

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

MinimumCapacity 獲取或設置該表最初的起始大小。該表中行的最初起始大小。默認值為 50。

Rows 獲取屬於該表的行的集合。

TableName 獲取或設置DataTable 的名稱。

 

1.4 DataTable是ADO.NET中的重要成員

 

  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 包括所有未更新的、新的和修改的數據行
Deleted 所有自上次調用AcceptChanges后刪除的數據行
ModifiedCurrent 所有自上次調用AcceptChanges后修改過的數據行
ModifiedOriginal 所有自上次調用AcceptChanges后original版本的數據行
New 所有自上次調用AcceptChanges后新添加的行
OriginalRows 返回初始數據行,包含unchanged和deleted 的
Unchanged 所有未更新的數據行

 

 

 

4.2 DataView的過濾器

    

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

 你可以用列名,邏輯和數字運算符和常量的任意合法組合組成表達式。以下是一些例子:
dv.RowFilter = "Country = 'USA'";
dv.RowFilter = "EmployeeID >5 AND Birthdate < #1/31/82#"
dv.RowFilter = "Description LIKE '*product*'"

讓我們來看一下過濾器的基本規則和運算符。
過濾字符串是表達式的邏輯連接。可以用AND,OR,NOT來連接成一個較短的表達式,也可以使用圓括號來組成子句,指定優先的運算。
通常包含列名的子句同字母、數字、日期或另一個列名進行比較。這里,可以使用關系運算符和算術運算符,如>=, <, >, +, *, % (取模)等等。
如果要選取的行並不能方便地通過算術或邏輯運算符表達,你可以使用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<6, Len(lastname) %2 =0, Len(lastname) %2 >0)

 

4.3 DataView 的排序 

 

DataView支持Sort屬性,可以用來對視圖中的內容排序。Sort由用逗號分隔的列名表達式進行排序。通過在任何列名后加ASC或者DESC限定詞,可以使得字段按照上升或者下降的順序排列。如果沒有方向限定詞,默認順序為ASC。
DataView是內存中的對象,所以排序在本地進行,無需調用數據庫服務器。

 

實例篇 

 

實例1.DataTable分組統計數據

 

 

Name

Subject

Scores

Jack

001

90

Jack

002

85.5

Tom

001

78.5

Jerry

001

59

Tom

002

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 < 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);

}

 

代碼 

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->DataTable dt = new DataTable();

            //創建連接
            SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["sql2005"].ConnectionString);

            SqlDataAdapter sda = new SqlDataAdapter("select * from test",conn);

            sda.Fill(dt);

            //將得到的數據轉成DataView
            DataView dv = new DataView(dt);

            //創建一個包含Name列的字符串數組
            String [] strColumns = { "Name" };

            //將dv視圖中不重復的Name列篩選出來
            DataTable dtTemp = dv.ToTable(true,strColumns);

            //克隆表結構給dtNew
            DataTable dtNew = dt.Clone();

            for (int i = 0; i < 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);
            }

            GridView1.DataSource = dtNew;
            GridView1.DataBind();

 

 

 


免責聲明!

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



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