DataTable 表示一个内存内关系数据的表,可以独立创建和使用,也可以由其他 .NET Framework 对象使用,最常见的情况是作为 DataSet 的成员使用。
DataTable 对象可通过使用 DataTable 构造函数来创建,或者可通过将构造函数参数传递到 DataSet 的 Tables 属性的 Add 方法(它是一个 DataTableCollection)来创建。
DataTable 对象可通过使用 DataAdapter 对象的 Fill 方法或 FillSchema 方法在 DataSet 内创建,或者可使用 DataSet 的 ReadXml、ReadXmlSchema 或 InferXmlSchema 方法从预定义的或推断的 XML 架构中创建。请注意,将一个 DataTable 作为成员添加到一个 DataSet 的 Tables 集合中后,不能再将其添加到任何其他 DataSet 的表集合中。
最初创建 DataTable 时,它是没有架构(结构)的。要定义表的架构,必须创建 DataColumn 对象并将其添加到表的 Columns 集合中。您也可以为表定义主键列,并且可以创建 Constraint 对象并将其添加到表的 Constraints 集合中。在为 DataTable 定义了架构之后,可通过将 DataRow 对象添加到表的 Rows 集合中来将数据行添加到表。
创建 DataTable 时,不需要为 TableName 属性提供值,您可以在其他时间指定属性,或者将其保留为空。但是,在将一个没有 TableName 值的表添加到 DataSet 中时,该表会得到一个从“Table”(表示 Table0)开始递增的默认名称 TableN。
[C#]
DataTable workTable = new DataTable("Customers");
DataSet custDS = new DataSet();
DataTable custTable = custDS.Tables.Add("CustTable");
DataTable 包含了由表的 Columns 属性引用的 DataColumn 对象的集合。这个列的集合与任何约束一起定义表的架构或结构。
通过使用 DataColumn 构造函数,或者通过调用表的 Columns 属性的 Add 方法(它是一个 DataColumnCollection),可在表内创建 DataColumn 对象。Add 方法将接受可选的 ColumnName、DataType 和 Expression 参数,并将创建新的 DataColumn 作为集合的成员。它也会接受现有的 DataColumn 对象并会将其添加到集合中,并会根据请求返回对所添加的 DataColumn 的引用。由于 DataTable 对象对任何数据源都不是特定的,所以在指定 DataColumn 的数据类型时会使用 .NET Framework 类型。
DataTable workTable = new DataTable("Customers");
DataColumn workCol = workTable.Columns.Add("CustID", typeof(Int32));
workCol.AllowDBNull = false;
workCol.Unique = true;
workTable.Columns.Add("CustLName", typeof(String));
workTable.Columns.Add("CustFName", typeof(String));
workTable.Columns.Add("Purchases", typeof(Double));
请注意,示例中用于 CustID 列的属性设置为不允许 DBNull 值并将值约束为唯一。但是,如果您将 CustID 列定义为表的主键列,AllowDBNull 属性就会自动设置为 false,并且 Unique 属性会自动设置为 true。有关更多信息,请参见为表定义主键。
在创建 DataTable 并使用列和约束定义其结构之后,您可以将新的数据行添加到表中。要添加新行,可将一个新变量声明为 DataRow 类型。调用 NewRow 方法时,将返回新的 DataRow 对象。然后,DataTable 会根据表的结构按 DataColumnCollection 的定义创建 DataRow 对象。
以下示例向新建的 Customers 表中添加了十行。
[C#]
DataRow workRow;
for (int i = 0; i <= 9; i++)
{
workRow = workTable.NewRow();
workRow[0] = i;
workRow[1] = "CustName" + i.ToString();
workTable.Rows.Add(workRow);
}
::您也可以通过传入值的数组(类型化为 Object),调用 Add 方法来添加新行,如下例所示。
[C#]
workTable.Rows.Add(new Object[] {1, "Smith"});
[C#]
workRow["CustLName"] = "Smith";
workRow[1] = "Smith";
workTable.Rows.Add(workRow);
------------------------------------------------------------
可以使用 DataTable 的 Rows 和 Columns 集合来访问 DataTable 中的内容。也可以根据包括搜索标准、排序顺序和行状态等特定标准,
使用 DataTable.Select 方法返回 DataTable 中数据的子集。此外,用主键值搜索特定行时,还可使用 DataRowCollection 的 Find
方法。
DataTable 对象的 Select 方法返回一组与指定条件匹配的 DataRow 对象。Select 采用筛选表达式、排序表达式和 DataViewRowState
的可选参数。筛选表达式根据 DataColumn 值(例如 LastName = 'Smith'
。排序表达式遵循用于为列排序的标准 SQL 约定,例如
LastName ASC, FirstName ASC
。有关编写表达式的规则,请参见 DataColumn 类的 Expression 属性。
[C#]
DataRow[] currRows = workTable.Select(null, null, DataViewRowState.CurrentRows);
if (currRows.Length < 1 )
Console.WriteLine("No Current Rows Found");
else
{
foreach (DataColumn myCol in workTable.Columns)
Console.Write("\t{0}", myCol.ColumnName);
Console.WriteLine("\tRowState");
foreach (DataRow myRow in currRows)
{
foreach (DataColumn myCol in workTable.Columns)
Console.Write("\t{0}", myRow[myCol]);
Console.WriteLine("\t" + myRow.RowState);
}
}
------------------------------------------------------
当您在 DataRow 中更改列值时,所做更改会立即置于行的 Current 状态中。然后,RowState 会设置为 Modified,并使用 DataRow 的
AcceptChanges 或 RejectChanges 方法来接受或拒绝所做更改。DataRow 还提供了三种可用于在编辑行时将行的状态挂起的方法。
这些方法是 BeginEdit、EndEdit 和 CancelEdit。
当您直接在 DataRow 中修改列值时,DataRow 会使用 Current、Default 和 Original 行版本来管理列值。除这些行版本以外,
BeginEdit、EndEdit 和 CancelEdit 方法还使用第四个行版本:Proposed。有关行版本的更多信息,请参见行状态与行版本。
在执行编辑操作(通过调用 BeginEdit 开始,并且通过使用 EndEdit 或 CancelEdit 或者通过调用 AcceptChanges 或 RejectChanges 结束)
的过程中,Proposed 行版本会存在。
在编辑操作过程中,您可以通过计算 DataTable 的 ColumnChanged 事件中的 ProposedValue 来将验证逻辑应用于各列。ColumnChanged
事件保存 DataColumnChangeEventArgs,可保持对正在更改的列和 ProposedValue 的引用。计算了建议值后,可以对其进行修改或取消编辑。
编辑结束时,行从 Proposed 状态中移出。
您可以通过调用 EndEdit 来确认编辑,也可以通过调用 CancelEdit 来取消编辑。请注意,尽管 EndEdit 确实已确认您所做的编辑,但在调用
AcceptChanges 之前,DataSet 并没有实际接受更改。另外请注意,如果在 EndEdit 或 CancelEdit 编辑结束之前调用 AcceptChanges,
编辑将会终止,并接受 Current 和 Original 行版本的 Proposed 行值。调用 RejectChanges 会以同样的方式结束编辑,并放弃 Current
和 Proposed 行版本。在调用 AcceptChanges 或 RejectChanges 之后调用 EndEdit 或 CancelEdit 不会起作用,因为编辑已经结束。
[C#]
DataTable workTable = new DataTable();
workTable.Columns.Add("LastName", typeof(String));
workTable.ColumnChanged += new DataColumnChangeEventHandler(OnColumnChanged);
DataRow workRow = workTable.NewRow();
workRow[0] = "Smith";
workTable.Rows.Add(workRow);
workRow.BeginEdit();
// Causes the ColumnChanged event to write a message and cancel the edit.
workRow[0] = "";
workRow.EndEdit();
// Displays "Smith, New".
Console.WriteLine("{0}, {1}", workRow[0], workRow.RowState);
protected static void OnColumnChanged(Object sender, DataColumnChangeEventArgs args)
{
if (args.Column.ColumnName == "LastName")
if (args.ProposedValue.ToString() == "")
{
Console.WriteLine("Last Name cannot be blank. Edit canceled.");
args.Row.CancelEdit();
}
}