在数据表(DataTable)中操作数据
2006-11-07 16:15
183 查看
在 DataSet 中创建 DataTable 之后,您执行的活动可以与使用数据库中的表时执行的活动相同。您可以添加、查看、编辑和删除表中的数据;可以监视错误和事件;并且可以查询表中的数据。在修改 DataTable 中的数据时,您也可以验证更改是否正确,并决定是否以编程方式接受更改或拒绝更改。
本节内容
将数据添至表中:说明如何创建新行并将其添至表中。
查看表中数据:说明如何访问行中的数据,包括数据的原始版本和当前版本。
编辑表中的数据:说明如何修改行中的数据,包括挂起对行的更改,直至验证并接受了建议的更改。
行状态与行版本:提供有关行的不同状态的信息。
从表中删除行:说明如何从表中移除行。
添加和读取行错误信息:说明如何按行插入错误信息,以用于解决有关应用程序内行中数据的问题。
接受或拒绝对行的更改:说明如何接受或拒绝对行的更改。
处理 DataTable 事件:提供可用于 DataTable 的事件的相关信息,包括修改列值和添加或删除行时的事件。
本节内容
将数据添至表中:说明如何创建新行并将其添至表中。
在创建 DataTable 并使用列和约束定义其结构之后,您可以将新的数据行添至表中。要添加新行,可将一个新变量声明为 DataRow 类型。调用 NewRow 方法时,将返回新的 DataRow 对象。然后,DataTable 会根据表的结构按 DataColumnCollection 的定义创建 DataRow 对象。 以下示例演示了如何通过调用 NewRow 方法来创建新行。 [Visual Basic] Dim workRow As DataRow = workTable.NewRow() [C#] DataRow workRow = workTable.NewRow(); 然后您可以使用索引或列名来操作新添加的行,如下例所示。 [Visual Basic] workRow("CustLName") = "Smith" workRow(1) = "Smith" [C#] workRow["CustLName"] = "Smith"; workRow[1] = "Smith"; 在将数据插入新行后,Add 方法可用于将行添至 DataRowCollection,如以下代码所示。 [Visual Basic] workTable.Rows.Add(workRow) [C#] workTable.Rows.Add(workRow); 您也可以通过传入值的数组(类型化为 Object),调用 Add 方法来添加新行,如下例所示。 [Visual Basic] workTable.Rows.Add(new Object() {1, "Smith"}) [C#] workTable.Rows.Add(new Object[] {1, "Smith"}); 将类型化为 Object 的值的数组传递到 Add 方法,可在表内创建新行并将其列值设置为对象数组中的值。请注意,数组中的值会根据它们在表中出现的顺序相继与各列匹配。 以下示例将十行添至新建的 Customers 表中。 [Visual Basic] Dim workRow As DataRow Dim I As Integer For I = 0 To 9 workRow = workTable.NewRow() workRow(0) = I workRow(1) = "CustName" & I.ToString() workTable.Rows.Add(workRow) Next [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); } |
可以使用 DataTable 的 Rows 和 Columns 集合来访问 DataTable 中的内容。也可以根据包括搜索标准、排序顺序和行状态等特定标准,使用 DataTable.Select 方法返回 DataTable 中数据的子集。此外,用主键值搜索特定行时,还可使用 DataRowCollection 的 Find 方法。 DataTable 对象的 Select 方法返回一组与指定条件匹配的 DataRow 对象。Select 采用筛选表达式、排序表达式和 DataViewRowState 的可选参数。筛选表达式根据 DataColumn 值(例如 LastName = 'Smith'。排序表达式遵循用于为列排序的标准 SQL 约定,例如 LastName ASC, FirstName ASC。有关编写表达式的规则,请参阅 DataColumn 类的 Expression 属性。 提示 如果您将对 DataTable 的 Select 方法执行多次调用,可通过先为 DataTable 创建 DataView 来提高性能。创建 DataView 会为表中的行编制索引。然后,Select 方法会使用该索引,这样将显著缩短生成查询结果的时间。有关为 DataTable 创建 DataView 的信息,请参阅创建和使用 DataView。 Select 方法基于 DataViewRowState 确定要查看或操作的行的版本。下表说明了可能的 DataViewRowState 枚举值。
[Visual Basic] Dim myCol As DataColumn Dim myRow As DataRow Dim currRows() As DataRow = workTable.Select(Nothing, Nothing, DataViewRowState.CurrentRows) If (currRows.Length < 1 ) Then Console.WriteLine("No Current Rows Found") Else For Each myCol in workTable.Columns Console.Write(vbTab & myCol.ColumnName) Next Console.WriteLine(vbTab & "RowState") For Each myRow In currRows For Each myCol In workTable.Columns Console.Write(vbTab & myRow(myCol).ToString()) Next Dim rowState As String = System.Enum.GetName(myRow.RowState.GetType(), myRow.RowState) Console.WriteLine(vbTab & rowState) Next End If [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); } } Select 方法可用于返回具有不同 RowState 值或字段值的行。以下示例返回一个引用所有已删除行的 DataRow 数组,并返回另一个引用所有已排序行(按照 CustLName 排序,其中 CustID 列大于 5)的 DataRow 数组。 [Visual Basic] ' Retrieve all deleted rows. Dim delRows() As DataRow = workTable.Select(Nothing, Nothing, DataViewRowState.Deleted) ' Retrieve rows where CustID > 5, and order by CustLName. Dim custRows() As DataRow = workTable.Select("CustID > 5", "CustLName ASC") [C#] // Retrieve all deleted rows. DataRow[] delRows = workTable.Select(null, null, DataViewRowState.Deleted); // Retrieve rows where CustID > 5, and order by CustLName. DataRow[] custRows = workTable.Select("CustID > 5", "CustLName ASC"); |
当您在 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 不会起作用,因为编辑已经结束。 以下示例演示了如何将 BeginEdit 与 EndEdit 和 CancelEdit 一起使用。本示例也会检查 ColumnChanged 事件中的 ProposedValue,并决定是否取消编辑。 [Visual Basic] Dim workTable As DataTable = New DataTable workTable.Columns.Add("LastName", Type.GetType("System.String")) AddHandler workTable.ColumnChanged, New DataColumnChangeEventHandler(AddressOf OnColumnChanged) Dim workRow As DataRow = 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) Private Shared Sub OnColumnChanged(sender As Object, args As DataColumnChangeEventArgs) If args.Column.ColumnName = "LastName" Then If args.ProposedValue.ToString() = "" Then Console.WriteLine("Last Name cannot be blank. Edit canceled.") args.Row.CancelEdit() End If End If End Sub [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(); } } |
ADO.NET 用行状态和版本管理表中的行。行状态表示行的状态。当修改行时,行版本会维护存储于行中的值,包括当前值、原始值和默认值。例如,修改了某行中的一列后,该行会有一个 Modified 的行状态,并且会存在两个行版本:Current(包含当前行值)和 Original(包含修改该列前的行值)。 每个 DataRow 对象都具有 RowState 属性,您可以检查此属性来确定行的当前状态。下表给出了对各 RowState 枚举值的简要说明。
通过用列引用来传递 DataRowVersion 参数,您可以查看行的不同行版本,如下例所示。 [Visual Basic] Dim custRow As DataRow = custTable.Rows(0) Dim custID As String = custRow("CustomerID", DataRowVersion.Original).ToString() [C#] DataRow custRow = custTable.Rows[0]; string custID = custRow["CustomerID", DataRowVersion.Original].ToString(); 下表给出了各 DataRowVersion 枚举值的简要说明。
DataRow.HasVersion(DataRowVersion.Original)对新添加的行将返回 false。 例如,以下代码示例显示了表中所有已删除行的值。已删除的行没有 Current 行版本,因此在访问列值时必须传递 DataRowVersion.Original。 [Visual Basic] Dim catTable As DataTable = catDS.Tables("Categories") Dim delRows() As DataRow = catTable.Select(Nothing, Nothing, DataViewRowState.Deleted) Console.WriteLine("Deleted rows:" & vbCrLf) Dim catCol As DataColumn Dim delRow As DataRow For Each catCol In catTable.Columns Console.Write(catCol.ColumnName & vbTab) Next Console.WriteLine() For Each delRow In delRows For Each catCol In catTable.Columns Console.Write(delRow(catCol, DataRowVersion.Original) & vbTab) Next Console.WriteLine() Next [C#] DataTable catTable = catDS.Tables["Categories"]; DataRow[] delRows = catTable.Select(null, null, DataViewRowState.Deleted); Console.WriteLine("Deleted rows:/n"); foreach (DataColumn catCol in catTable.Columns) Console.Write(catCol.ColumnName + "/t"); Console.WriteLine(); foreach (DataRow delRow in delRows) { foreach (DataColumn catCol in catTable.Columns) Console.Write(delRow[catCol, DataRowVersion.Original] + "/t"); Console.WriteLine(); } |
用于从 DataTable 对象中删除 DataRow 对象的方法有两种:DataRowCollection 对象的 Remove 方法和 DataRow 对象的 Delete 方法。Remove 方法从 DataRowCollection 中删除 DataRow,而 Delete 方法只将行标记为删除。当应用程序调用 AcceptChanges 方法时,才会发生实际的删除。通过使用 Delete,您可以在实际删除之前先以编程方式检查哪些行标记为删除。如果将行标记为删除,其 RowState 属性会设置为 Deleted。 在将 DataSet 或 DataTable 与 DataAdapter 和关系型数据源一起使用时,用 DataRow 的 Delete 方法移除行。Delete 方法只是在 DataSet 或 DataTable 中将行标记为 Deleted,而不会移除它。而 DataAdapter 在遇到标记为 Deleted 的行时,会执行其 DeleteCommand 以在数据源中删除该行。然后,就可以用 AcceptChanges 方法永久移除该行。如果使用 Remove 删除该行,则该行将从表中完全移除,但 DataAdapter 不会在数据源中删除该行。 DataRowCollection 的 Remove 方法采用 DataRow 作为参数,并将其从集合中移除,如下例所示。 [Visual Basic] workTable.Rows.Remove(workRow) [C#] workTable.Rows.Remove(workRow); 作为对比,以下示例演示了如何调用 DataRow 上的 Delete 方法来将其 RowState 改为 Deleted。 [Visual Basic] workRow.Delete [C#] workRow.Delete(); 如果将行标记为删除,并且调用 DataTable 对象的 AcceptChanges 方法,该行就会从 DataTable 中移除。相比之下,如果调用 RejectChanges,行的 RowState 就会恢复到被标记为 Deleted 之前的状态。 注意 如果 DataRow 的 RowState 是 Added,则意味着已将其添至表中,然后将其标记为 Deleted,从表中移除。 |
为了避免在编辑 DataTable 中的值时每次发生行错误都必须响应,可将错误信息添至行中,以便以后使用。DataRow 对象通过对各行提供 RowError 属性来支持此功能。将数据添至 DataRow 的 RowError 属性会将 DataRow 的 HasErrors 属性标记为 true。如果 DataRow 是 DataTable 的组成部分,且 DataRow.HasErrors 是 true,则 DataTable.HasErrors 属性也是 true。这也适用于 DataTable 所属的 DataSet。为错误做测试时,可以检查 HasErrors 属性以确定错误信息是否已添至所有行。如果 HasErrors 为 true,则可使用 DataTable 的 GetErrors 方法以便只返回和检查有错误的行,如下例所示。 [Visual Basic] Dim workTable As DataTable = New DataTable("Customers") workTable.Columns.Add("CustID", Type.GetType("System.Int32")) workTable.Columns.Add("Total", Type.GetType("System.Double")) AddHandler workTable.RowChanged, New DataRowChangeEventHandler(AddressOf OnRowChanged) Dim I As Int32 For I = 0 To 10 workTable.Rows.Add(New Object() {I, I*100}) Next If workTable.HasErrors Then Console.WriteLine("Errors In Table " & workTable.TableName) Dim myRow As DataRow For Each myRow In workTable.GetErrors() Console.WriteLine("CustID = " & myRow("CustID").ToString()) Console.WriteLine(" Error = " & myRow.RowError & vbCrLf) Next End If Private Shared Sub OnRowChanged(sender As Object, args As DataRowChangeEventArgs) ' Check for zero values. If CDbl(args.Row("Total")) = 0 Then args.Row.RowError = "Total cannot be 0." End Sub [C#] DataTable workTable = new DataTable("Customers"); workTable.Columns.Add("CustID", typeof(Int32)); workTable.Columns.Add("Total", typeof(Double)); workTable.RowChanged += new DataRowChangeEventHandler(OnRowChanged); for (int i = 0; i < 10; i++) workTable.Rows.Add(new Object[] {i, i*100}); if (workTable.HasErrors) { Console.WriteLine("Errors In Table " + workTable.TableName); foreach (DataRow myRow in workTable.GetErrors()) { Console.WriteLine("CustID = " + myRow["CustID"]); Console.WriteLine(" Error = " + myRow.RowError + "/n"); } } protected static void OnRowChanged(Object sender, DataRowChangeEventArgs args) { // Check for zero values. if (args.Row["Total"].Equals(0D)) args.Row.RowError = "Total cannot be 0."; } |
在检验过对 DataTable 中的数据所做更改的准确性之后,可使用 DataRow、DataTable 或 DataSet 的 AcceptChanges 方法来接受更改,此方法会将 Current 行值设置为 Original 值,并会将 RowState 属性设置为 Unchanged。接受或拒绝更改会清除所有 RowError 信息,并将 HasErrors 属性设置为 false。接受或拒绝更改还可以影响在数据源中更新数据。有关更多信息,请参阅使用 DataAdapter 和 DataSet 更新数据库。 如果 DataTable 上存在外键约束,使用 AcceptChanges 和 RejectChanges 接受或拒绝的更改就会根据 ForeignKeyConstraint.AcceptRejectRule 传播至 DataRow 的子行。 以下示例检查有错误的行,在适用之处解决错误,拒绝无法解决错误的行。请注意,对于解决的错误,RowError 值会重置为空字符串,导致将 HasErrors 属性设置为 false。当解决或拒绝了所有的有错误的行时,就会调用 AcceptChanges 来接受对整个 DataTable 的所有更改。 [Visual Basic] If workTable.HasErrors Then Dim errRow As DataRow For Each errRow in workTable.GetErrors() If errRow.RowError = "Total cannot exceed 1000." Then errRow("Total") = 1000 errRow.RowError = "" ' Clear the error. Else errRow.RejectChanges() End If Next End If workTable.AcceptChanges() [C#] if (workTable.HasErrors) { foreach (DataRow errRow in workTable.GetErrors()) { if (errRow.RowError == "Total cannot exceed 1000.") { errRow["Total"] = 1000; errRow.RowError = ""; // Clear the error. } else errRow.RejectChanges(); } } workTable.AcceptChanges(); |
DataTable 对象提供一系列可由应用程序处理的事件。下表说明了 DataTable 事件。
[Visual Basic] AddHandler workTable.ColumnChanged, New DataColumnChangeEventHandler(AddressOf OnColumnChanged) AddHandler workTable.ColumnChanging, New DataColumnChangeEventHandler(AddressOf OnColumnChanging) AddHandler workTable.RowChanged, New DataRowChangeEventHandler(AddressOf OnRowChanged) AddHandler workTable.RowChanging, New DataRowChangeEventHandler(AddressOf OnRowChanging) Private Shared Sub OnColumnChanged(sender As Object, args As DataColumnChangeEventargs) Console.Write(" ColumnChanged: ") Console.Write(args.Column.ColumnName & " changed to '" & args.ProposedValue.ToString() & "'" & vbCrLf) End Sub Private Shared Sub OnColumnChanging(sender As Object, args As DataColumnChangeEventargs) Console.Write("ColumnChanging: ") Console.Write(args.Column.ColumnName & " equals '" & args.Row(args.Column).ToString() & _ "', changing to '" & args.ProposedValue.ToString() & "'" & vbCrLf) End Sub Private Shared Sub OnRowChanging(sender As Object, args As DataRowChangeEventargs) If args.Action <> DataRowAction.Nothing Then Dim actionStr As String actionStr = System.Enum.GetName(args.Action.GetType(), args.Action) Console.WriteLine(" RowChanging: Action = " & actionStr & ", CustID = " & args.Row("CustID").ToString()) End If End Sub Private Shared Sub OnRowChanged(sender As Object, args As DataRowChangeEventargs) If args.Action <> DataRowAction.Nothing Then Dim actionStr As String actionStr = System.Enum.GetName(args.Action.GetType(), args.Action) Console.WriteLine(" RowChanged: Action = " & actionStr & ", CustID = " & args.Row("CustID").ToString()) End If End Sub [C#] workTable.ColumnChanged += new DataColumnChangeEventHandler(OnColumnChanged); workTable.ColumnChanging += new DataColumnChangeEventHandler(OnColumnChanging); workTable.RowChanged += new DataRowChangeEventHandler(OnRowChanged); workTable.RowChanging += new DataRowChangeEventHandler(OnRowChanging); protected static void OnColumnChanged(object sender, DataColumnChangeEventArgs args) { Console.Write(" ColumnChanged: "); Console.Write(args.Column.ColumnName + " changed to '" + args.ProposedValue + "'/n"); } protected static void OnColumnChanging(object sender, DataColumnChangeEventArgs args) { Console.Write("ColumnChanging: "); Console.Write(args.Column.ColumnName + " equals '" + args.Row[args.Column] + "', changing to '" + args.ProposedValue + "'/n"); } protected static void OnRowChanging(object sender, DataRowChangeEventArgs args) { if (args.Action != DataRowAction.Nothing) Console.WriteLine(" RowChanging: Action = " + args.Action + ", CustID = " + args.Row["CustID"]); } protected static void OnRowChanged(object sender, DataRowChangeEventArgs args) { if (args.Action != DataRowAction.Nothing) Console.WriteLine(" RowChanged: Action = " + args.Action + ", CustID = " + args.Row["CustID"]); } |
相关文章推荐
- DataTable相关操作,筛选,取前N条数据,去重复行,获取指定列数据
- c#基础数据操作之遍历DataTable并输出
- 使用VSIUAL C#.NET操作Excel -把DataTable中的数据写入Excel
- 使用VSIUAL C#.NET操作Excel -把DataTable中的数据写入Excel
- XML操作多行数据(即DataTable)的类(可直接使用)
- dataTable 操作某条数据后刷新是否保留在当前页的方法
- asp.net DataTable相关操作集锦(筛选,取前N条数据,去重复行,获取指定列数据等)
- DataTable相关操作,筛选,取前N条数据,获取指定列数据
- DataTable 基础操作一 往DataTable中添加数据
- juqery datatable ajax请求后台数据 并为表格添加操作列
- DataTable 数据更新、删除、插入 数据库 操作
- DataGridView中绑定DataTable数据及相关操作实现代码
- C#操作DataTable方法实现过滤、取前N条数据及获取指定列数据列表的方法
- DataTable相关操作,筛选,取前N条数据,去重复行,获取指定列数据
- 在ASP.NET 2.0中操作数据之六十八:为DataTable添加额外的列
- 使用VSIUAL C#.NET操作Excel -把DataTable中的数据写入Excel
- DBHelper,ADO直接操作数据库,扩展DataTable操作数据裤的方法
- 使用OpenXml操作Excel,创建excel,导入DataTable的数据等
- DataTable相关操作,筛选,取前N条数据,获取指定列数据
- 关于datatable的一些操作以及使用adapter对数据的操作