从DataTable中删除特定行

时间:2011-04-13 11:21:34

标签: c# delete-row

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

  

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

我用来删除这段代码,

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

那么,问题是什么以及如何解决?你建议采用哪种方法?

14 个答案:

答案 0 :(得分:132)

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

而是使用For循环,例如:

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

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

答案 1 :(得分:105)

在每个人都跳过“你无法删除枚举”中的行之前,你需要首先意识到DataTables transactional ,并且在您致电 AcceptChanges()

之前,请不要在技术上清除更改

如果您在调用删除时看到此异常,则已处于待处理更改数据状态。例如,如果刚从数据库加载,如果你在foreach循环中,调用Delete会抛出异常。

BUT!但是!

如果从数据库加载行并调用函数“ 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()

答案 2 :(得分:15)

使用此解决方案:

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

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

答案 3 :(得分:13)

这对我有用,

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();

答案 4 :(得分:8)

DataRow[] dtr=dtPerson.select("name=Joe");
foreach(var drow in dtr)
{
   drow.delete();
}
dtperson.AcceptChanges();

我希望它能帮到你

答案 5 :(得分:4)

或者只是将 DataTable 行集合转换为列表:

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

答案 6 :(得分:3)

要从 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);

答案 7 :(得分:1)

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

解决方案:要么像Widor写的那样,要么使用两个循环。在第一次通过DataTable时,您只存储(在临时列表中)对要删除的行的引用。然后在临时列表的第二次传递中删除这些行。

答案 8 :(得分:1)

<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();
}

答案 9 :(得分:1)

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

问题是,在我的表中是约。 10000行,所以循环槽DataTable行非常慢。

最后,我找到了更快的解决方案,我将源DataTable的副本与期望的结果,明确的源DataTablemerge结果从临时DataTable复制到源1

注意:改为在Joe中搜索名为DataRow的{​​{1}}您必须搜索所有名称为name的记录(小相反的搜索方式)

有例子(Joe):

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; 以防万一没有结果(例如,如果您的Try/Catch不包含dtPerson name,它会抛出例外情况,所以你对你的表没有任何作用,它保持不变。

答案 10 :(得分:0)

我的应用程序中有一个数据集,我去设置更改(删除一行),但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);                 
    }           
}

答案 11 :(得分:0)

您可以尝试从数据表中获取和删除ID列

s

答案 12 :(得分:0)

我在这里看到了正确答案的各种点滴,但让我将它们汇总并解释几件事。

首先,AcceptChanges仅应用于将表上的整个事务标记为已验证并已提交。这意味着,如果您将DataTable用作绑定到例如SQL Server的数据源,则手动调用AcceptChanges将确保更改永远不会保存到SQL Server

这个问题更加令人困惑的是,实际上在两种情况下会引发异常,因此我们必须防止这两种情况。

1。修改IEnumerable的集合

我们无法在要枚举的集合中添加或删除索引,因为这样做可能会影响枚举器的内部索引。 解决此问题的方法有两种:要么在for循环中进行自己的索引编制,要么对枚举使用单独的集合(未经修改)。

2。尝试读取已删除的条目

由于数据表是事务性集合,因此可以将条目标记为删除,但仍会出现在枚举中。这意味着,如果您要求删除列"name"的条目,那么它将引发异常。 这意味着我们必须在查询列之前检查是否dr.RowState != DataRowState.Deleted

将它们放在一起

我们可能会变得混乱并手动执行所有操作,或者通过执行以下操作,让DataTable为我们完成所有工作,并使语句看起来更像是SQL调用:

string name = "Joe";
foreach(DataRow dr in dtPerson.Select($"name='{name}'"))
    dr.Delete();

通过调用DataTable的Select函数,我们的查询自动避免了DataTable中已删除的条目。并且由于Select函数返回一个匹配数组,因此我们调用dr.Delete()时不会修改正在枚举的集合。我还使用字符串插值对Select表达式进行了加分,以允许在不使代码嘈杂的情况下进行变量选择。

答案 13 :(得分:0)

在按钮中使用此方法的简单方法:

 var table = $('#example1').DataTable();
 table.row($(`#yesmediasec-${id}`).closest('tr')).remove( ).draw();

example1 = id表。 yesmediasec =该行中按钮的ID

使用它,一切都会好的