删除DataTable中的特定行

| 我想从DataTable中删除一些行,但它给出了这样的错误,   集合已修改;枚举操作可能无法执行 我用来删除此代码,
foreach(DataRow dr in dtPerson.Rows){
    if(dr[\"name\"].ToString()==\"Joe\")
        dr.Delete();
}
那么,问题是什么以及如何解决?您建议哪种方法?     
已邀请:
如果您从集合中删除某个项目,则该集合已被更改,您将无法继续对其进行枚举。 而是使用For循环,例如:
for(int i = dtPerson.Rows.Count-1; i >= 0; i--)
{
    DataRow dr = dtPerson.Rows[i];
    if (dr[\"name\"] == \"Joe\")
        dr.Delete();
}
dtPerson.AcceptChanges();
请注意,您要反向进行迭代,以避免在删除当前索引后跳过行。     
在每个人跳上“您无法删除Enumeration中的行”之前,您需要首先意识到DataTables是事务性的,并且从技术上讲,不要清除更改,直到您调用AcceptChanges() 如果在调用Delete时看到此异常,则您已经处于挂起更改数据状态。例如,如果您刚从数据库中加载,则如果您处于foreach循环中,则调用Delete会引发异常。 但!但! 如果您从数据库中加载行并调用函数\'AcceptChanges()\',则会将所有这些未完成的更改提交到DataTable。现在您可以遍历调用Delete()的行列表,而无需担心,因为它只是将行标记为Deletion,但是直到再次调用AcceptChanges()才提交。 我意识到这个回应有些过时了,但是我最近不得不处理类似的问题,希望这可以为将来使用10年代码的开发人员节省一些痛苦:) P.s.这是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()
    
使用此解决方案:
for(int i = dtPerson.Rows.Count-1; i >= 0; i--) 
{ 
    DataRow dr = dtPerson.Rows[i]; 
    if (dr[\"name\"] == \"Joe\")
        dr.Delete();
} 
如果删除行后要使用数据表,则会出现错误。因此,您可以做的是: 用
dtPerson.Rows.Remove(dr);
代替
dr.Delete();
    
这对我有用
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 Row集合转换为列表:
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);
    
问题出在哪里:禁止在foreach循环内从集合中删除项目。 解决方案:要么像Widor所写的那样做,要么使用两个循环。在第一次通过DataTable时,您仅存储(在临时列表中)对要删除的行的引用。然后在临时列表的第二遍中删除这些行。     
<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
行非常慢。 最后,我找到了更快的解决方案,在其中复制了源
DataTable
并获得了预期的结果,将源
DataTable
merge
的结果从临时ѭ12清除为​​源一。 注意:而是在称为“19ѭ”的“ 18”中搜索“ 17”,您必须搜索所有不具有名称“ 17”的记录(搜索的方式略有相反) 有例子(
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
我希望如此简短的解决方案能对某人有所帮助。 有
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;
当然,如果没有结果(例如,如果Your
dtPerson
不包含
name
Joe
它将抛出异常),我将使用
Try/Catch
,因此您对表不执行任何操作,它保持不变。     
我的应用程序中有一个数据集,我去设置了更改(删除一行),但
ds.tabales[\"TableName\"]
是只读的。然后我找到了解决方案。 这是一个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);                 
    }           
}
    
您尝试此操作以获取和删除数据表中的id列
if (dt1.Columns.Contains(\"ID\"))
{
    for (int i = dt1.Rows.Count - 1; i >= 0; i--)
    {
        DataRow dr = dt1.Rows[i];

        if (dr[\"ID\"].ToString() != \"\" && dr[\"ID\"].ToString() != null)
        {
            dr.Delete();
        }
    }

    dt1.Columns.Remove(\"ID\");
}
    
我在这里看到了正确答案的各种点滴,但让我将它们汇总并解释几件事。 首先,“ 33”仅应用于将表上的整个事务标记为已验证并已提交。这意味着,如果您将DataTable用作绑定到例如SQL Server的数据源,则手动调用
AcceptChanges
可以确保所做的更改永远不会保存到SQL Server。 使这个问题更令人困惑的是,实际上在两种情况下会引发异常,因此我们必须防止这两种情况。 1.修改IEnumerable的集合 我们无法在要枚举的集合中添加或删除索引,因为这样做可能会影响枚举器的内部索引。 解决此问题的方法有两种:要么在for循环中进行自己的索引编制,要么对枚举使用单独的集合(未经修改)。 2.尝试读取已删除的条目 由于DataTables是事务性集合,因此可以将条目标记为删除,但仍会出现在枚举中。这意味着,如果您向“ 35”列询问已删除的条目,则将引发异常。 这意味着我们必须在查询列之前检查是否为
dr.RowState != DataRowState.Deleted
。 全部放在一起 我们可能会变得凌乱并手动完成所有这些操作,或者通过执行以下操作,让DataTable为我们完成所有工作,并使语句看起来更像是SQL调用:
string name = \"Joe\";
foreach(DataRow dr in dtPerson.Select($\"name=\'{name}\'\"))
    dr.Delete();
通过调用DataTable的“ 38”函数,我们的查询将自动避免在DataTable中删除已删除的条目。并且由于
Select
函数返回一个匹配数组,因此当我们调用
dr.Delete()
时,我们正在枚举的集合不会被修改。我还使用字符串插值对Select表达式进行了加分,以允许在不使代码嘈杂的情况下进行变量选择。     

要回复问题请先登录注册