从DataTable中删除特定的行

我想从DataTable中删除一些行,但是会出现这样的错误,

collections被修改; 枚举操作可能不会执行

我用于删除这段代码,

foreach(DataRow dr in dtPerson.Rows){ if(dr["name"].ToString()=="Joe") dr.Delete(); } 

那么,这个问题是怎么解决的呢? 你build议哪种方法?

如果您从集合中删除某个项目,则该集合已被更改,您无法继续通过该项目进行枚举。

相反,使用For循环,例如:

 for(int i = dtPerson.Rows.Count-1; i >= 0; i--) { DataRow dr = dtPerson.Rows[i]; if (dr["name"] == "Joe") dr.Delete(); } 

请注意,您正在反向迭代,以避免在删除当前索引后跳过一行。

在每个人都跳到' 你不能删除Enumeration '行列的之前,你需要首先意识到DataTables是事务性的 ,在你调用AcceptChanges()之前不会在技术上清除更改,

如果您在调用Delete时看到此exception,那么您已经处于未决更改数据状态 。 例如,如果你刚刚从数据库加载,调用Delete将抛出一个exception,如果你在一个foreach循环。

但! 但!

如果从数据库加载行并调用函数“ AcceptChanges() ”,则将所有这些待处理的更改提交给DataTable。 现在,您可以遍历调用Delete()的行的列表,而不必考虑世界上的情况,因为它只是在删除行上标记行,但在您再次调用AcceptChanges()

我意识到这个答复有点过时,但最近我不得不面对一个类似的问题,希望这为将来的开发人员工作10年的代码节省了一些痛苦:)


Ps这是一个由Jeff添加的简单代码示例:

 C# YourDataTable.AcceptChanges(); foreach (DataRow row in YourDataTable.Rows) { // If this row is offensive then row.Delete(); } YourDataTable.AcceptChanges(); VB.Net ds.Tables(0).AcceptChanges() For Each row In ds.Tables(0).Rows ds.Tables(0).Rows(counter).Delete() counter += 1 Next ds.Tables(0).AcceptChanges() 

用这个解决scheme:

 for(int i = dtPerson.Rows.Count-1; i >= 0; i--) { DataRow dr = dtPerson.Rows[i]; if (dr["name"] == "Joe") dr.Delete(); } 

如果在删除行之后要使用该数据表,将会出现错误。 所以你可以做的是:replacedr.Delete();dtPerson.Rows.Remove(dr);

这对我有用,

 List<string> lstRemoveColumns = new List<string>() { "ColValue1", "ColVal2", "ColValue3", "ColValue4" }; List<DataRow> rowsToDelete = new List<DataRow>(); foreach (DataRow row in dt.Rows) { if (lstRemoveColumns.Contains(row["ColumnName"].ToString())) { rowsToDelete.Add(row); } } foreach (DataRow row in rowsToDelete) { dt.Rows.Remove(row); } dt.AcceptChanges(); 
 DataRow[] dtr=dtPerson.select("name=Joe"); foreach(var drow in dtr) { drow.delete(); } dtperson.AcceptChanges(); 

我希望这会帮助你

或者只是将一个DataTable 行集合转换成一个列表:

 foreach(DataRow dr in dtPerson.Rows.ToList()) { if(dr["name"].ToString()=="Joe") dr.Delete(); } 

要从DataTable中删除整行 ,请这样做

 DataTable dt = new DataTable(); //User DataTable DataRow[] rows; rows = dt.Select("UserName = 'KarthiK'"); //'UserName' is ColumnName foreach (DataRow row in rows) dt.Rows.Remove(row); 
 <asp:GridView ID="grd_item_list" runat="server" AutoGenerateColumns="false" Width="100%" CssClass="table table-bordered table-hover" OnRowCommand="grd_item_list_RowCommand"> <Columns> <asp:TemplateField HeaderText="No"> <ItemTemplate> <%# Container.DataItemIndex + 1 %> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="Actions"> <ItemTemplate> <asp:Button ID="remove_itemIndex" OnClientClick="if(confirm('Are You Sure to delete?')==true){ return true;} else{ return false;}" runat="server" class="btn btn-primary" Text="REMOVE" CommandName="REMOVE_ITEM" CommandArgument='<%# Container.DataItemIndex+1 %>' /> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> **This is the row binding event** protected void grd_item_list_RowCommand(object sender, GridViewCommandEventArgs e) { item_list_bind_structure(); if (ViewState["item_list"] != null) dt = (DataTable)ViewState["item_list"]; if (e.CommandName == "REMOVE_ITEM") { var RowNum = Convert.ToInt32(e.CommandArgument.ToString()) - 1; DataRow dr = dt.Rows[RowNum]; dr.Delete(); } grd_item_list.DataSource = dt; grd_item_list.DataBind(); } 

我知道这是非常古老的问题,我前几天也有类似的情况。

问题是,在我的桌子是约。 10000行,所以循环低谷的DataTable行非常慢。

最后,我发现更快的解决scheme,在那里我复制源DataTable与所需的结果,清除源DataTablemerge结果从临时DataTable到源之一。

注意 :改为在DataRowsearch名为Joe name您必须search所有不具有名称Joelogging(与search的方式相反)

有例子( vb.net ):

 'Copy all rows into tmpTable whose not contain Joe in name DataRow Dim tmpTable As DataTable = drPerson.Select("name<>'Joe'").CopyToTable 'Clear source DataTable, in Your case dtPerson dtPerson.Clear() 'merge tmpTable into dtPerson (rows whose name not contain Joe) dtPerson.Merge(tmpTable) tmpTable = Nothing 

我希望这个较短的解决scheme将有助于某人。

c#代码(不知道是否正确,因为我使用在线转换器:():

 //Copy all rows into tmpTable whose not contain Joe in name DataRow DataTable tmpTable = drPerson.Select("name<>'Joe'").CopyToTable; //Clear source DataTable, in Your case dtPerson dtPerson.Clear(); //merge tmpTable into dtPerson (rows whose name not contain Joe) dtPerson.Merge(tmpTable); tmpTable = null; 

当然,如果没有结果(例如,如果你的dtPerson不包含name Joe ,它将抛出exception),我使用了Try/Catch ,所以你对你的表不做任何处理。

问题在哪里:禁止从foreach循环中的集合中删除项目。

解决scheme:或者像Widor写的那样,或者使用两个循环。 在DataTable的第一遍中,只存储(在临时列表中)对要删除的行的引用。 然后在第二遍你的临时列表中删除这些行。

我有一个数据集在我的应用程序,我去设置更改(删除行),但ds.tabales["TableName"]是只读的。 然后我发现这个解决scheme。

这是一个WPF的C#应用程序,

 try { var results = from row in ds.Tables["TableName"].AsEnumerable() where row.Field<string>("Personalid") == "47" select row; foreach (DataRow row in results) { ds.Tables["TableName"].Rows.Remove(row); } }