【发布时间】:2010-05-26 13:08:57
【问题描述】:
如何在满足自定义条件的 DataTable 行的循环中删除特定的 DataRows - 让我们说具有偶数索引的行 -? (不使用 LINQ)
谢谢
【问题讨论】:
标签: c# .net ado.net datatable datarow
如何在满足自定义条件的 DataTable 行的循环中删除特定的 DataRows - 让我们说具有偶数索引的行 -? (不使用 LINQ)
谢谢
【问题讨论】:
标签: c# .net ado.net datatable datarow
这取决于您所说的“删除”。
如果您的意思是将它们标记为已删除,只需在循环中访问每一行时调用 Delete() 方法即可。然后,您需要在数据表上调用 AcceptChanges() 以完成删除 - 大概是在您更新数据库之后(如果涉及)。
foreach( DataRow row in someTable.Rows )
{
if( /* your condition here */ )
row.Delete();
}
someTable.AcceptChanges();
如果您的意思是从 DataTable 中删除它,那么您需要分两次这样做:
List<DataRow> rowsToDelete = new List<DataRow>();
foreach( DataRow row in someTable.Rows )
{
if( /* your condition here */ )
{
rowsToDelete.Add( row );
}
}
foreach( DataRow row in rowsToDelete )
{
someTable.Rows.Remove( row );
}
值得指出的是,您始终可以使用第一种方法来删除行 - 因为将行标记为 Deleted 然后接受更改会自动将它们从表中删除。但是,有时从Rows 集合中删除DataRow 对象会更加清晰和高效。
【讨论】:
foreach 循环中使用Remove(),因为该函数会更改集合的状态。
试试这个例子
DataTable table = new DataTable();
table.Columns.Add("Foo",typeof(int));
for (int i = 0; i < 10; i++)
table.Rows.Add(i);
for (int i = table.Rows.Count -1; i >=0; i--)
{
// sample removes all even foos
if ((int)table.Rows[i]["Foo"] % 2 == 0)
table.Rows.RemoveAt(i);
}
【讨论】:
i++ 移动到 for 循环内并且仅在不删除时增加,也可以执行前向循环 (0 -> Count-1)。 if (...) remove() else i++
如果您想要一个比上述建议更短的解决方案,请尝试遍历结果列表,并使用像 sub(x) 这样的 lambda 来删除每一行。
dt.Select("Column1 > 0").ToList.ForEach(Sub(x) dt.Rows.Remove(x))
【讨论】:
另一种方法是
DataRow[] DrArrCheck = DataTableName.Select("ID > 0");
foreach(DataRow DrCheck in DrArrCheck)
{
DataTableName.Rows.Remove(DrCheck);
}
【讨论】:
public static void DeleteRowsFromDataTable(DataTable dataTable, string columnName, string columnValue)
{
IEnumerable<DataRow> dataRows = (from t in dataTable.AsEnumerable()
where t.Field<string>(columnName) == columnValue
select t);
foreach (DataRow row in dataRows)
dataTable.Rows.Remove(row);
}
【讨论】:
要删除多行(例如 100,000 行中的 50,000 行),复制数据库比执行 datatable.Rows.Remove(row) 或 row.Delete() 快得多。例如:
DataRow[] rowsToKeep = datatable.Select("ID > 50000");
DataTable tempDataTable= rowsToKeep.CopyToDataTable;
dataTable.Clear();
dataTable.Merge(tempDataTable);
tempDataTable.Dispose();
【讨论】:
尝试迭代 Select() 的结果。这与其他答案非常相似,但我觉得它最直接
DataRow[] r = table.Select();
for (int i = 0; i < r.Length; i++)
{
if (i % 2 == 0)
r[i].Delete();
}
【讨论】:
我一直使用 LBushkin 的“两阶段”方法,我最终决定为它编写一个函数是值得的:
public delegate bool DataRowComparer(DataRow dr);
public static void RemoveDataRows(DataTable table, DataRowComparer drc)
{
List<DataRow> RowsToRemove = new List<DataRow>();
foreach (DataRow dr in table.Rows)
if (drc(dr))
RowsToRemove.Add(dr);
foreach (DataRow dr in RowsToRemove)
table.Rows.Remove(dr);
}
现在我可以用一行代码删除行(例如):
RemoveDataRows(dt, row => row["StringVal"].ToString() == "B" && (Int16)(row["NumberVal"]) >= 4);
如果这对任何人都有帮助...
(感谢任何进一步缩写的方法。)
【讨论】:
我就是这样做的。
for (int i = RowNumber.Count - 1; i >= 0; i--)
{
dt.Rows.RemoveAt(Int32.Parse(RowNumber[i]));
}
missingNotesGV.DataSource = dt;
missingNotesGV.DataBind();
反向执行 for 循环很重要,否则如果除了其他位置的行之外还要删除末尾的行,则会出现错误。
【讨论】:
当我遇到这个问题时,我就是这样做的。
Dim index As Integer = 0
Dim count As Integer = resultsDT.Rows.Count - 1
For i As Integer = 0 To count
If resultsDT.Rows(index).Item("something") = "something" Then
resultsDT.Rows(index).Delete()
resultsDT.AcceptChanges()
index = index - 1
End If
index = index + 1
i = i + 1
Next
【讨论】:
试试这个
foreach(DataRow oRow in YourDataTable.Rows)
{
if ("Check You Condition")
{
YourDataTable.Rows.Remove(oRow);
}
}
【讨论】: