简体   繁体   English

从datatable中删除行会导致错误

[英]deleting rows from datatable causes error

I am trying to remove rows that are not needed from a DataTable . 我试图从DataTable删除不需要的行。 Basically, there may be several rows where the itemID is identical. 基本上, itemID可能有几行相同。 I want to find the rows where the column "failEmail" = "fail" , and using the itemID of those rows, remove all rows from the emails DataTable that have the same itemID . 我想找到列"failEmail" = "fail" ,并使用这些行的itemID ,从电子邮件DataTable中删除具有相同itemID所有行。

Here is what I have tried: 这是我尝试过的:

System.Diagnostics.Debug.Print(emails.Rows.Count.ToString() + " emails!");

// create a list of the email IDs for records that will be deleted
List<DataRow> rows2Delete = new List<DataRow>();

foreach (DataRow dr in emails.Rows) 
{
   if (dr["failEmail"].ToString().ToLower() == "fail") 
   {
      rows2Delete.Add(dr);
   }
}

foreach (DataRow row in rows2Delete)
{
   DataRow[] drRowsToCheck =emails.Select("itemID ='" + row["itemID"].ToString()  +"'");
   foreach (DataRow drCheck in drRowsToCheck)
   {
      emails.Rows.RemovedDrCheck);
      emails.AcceptChanges();
   }
}

Here is the error message I am getting on the second pass: 以下是我在第二次传递时收到的错误消息:

This row has been removed from a table and does not have any data. 此行已从表中删除,并且没有任何数据。 BeginEdit() will allow creation of new data in this row BeginEdit()将允许在此行中创建新数据

How can I do what I need to without throwing errors like that? 如何在不抛出错误的情况下做我需要的工作? Is there a better way like using a LiNQ query? 有没有比使用LiNQ查询更好的方法?

The problem is that when the same itemID has multiple entries with 'fail', you are trying to remove them multiple times. 问题是,当同一个itemID有多个条目为“fail”时,您试图多次删除它们。

// 1. Find the Unique itemIDs to remove
var idsToRemove = emails.Select("failEmail = 'fail'").Select (x => x["itemID"]).Distinct();
// 2. Find all the rows that match the itemIDs found
var rowsToRemove = emails.Select(string.Format("itemID in ({0})", string.Join(", ", idsToRemove)));
// 3. Remove the found rows.
foreach(var rowToRemove in rowsToRemove)
{
    emails.Rows.Remove(rowToRemove);
}
emails.AcceptChanges();

this is what I ended up doing, based on an answer I got from MSDN c# Forums: 这是我最终做的,基于我从MSDN获得的答案c#论坛:

create an extension on DataTable to enable LINQ euering of the Datatable: 在DataTable上创建一个扩展,以启用Datatable的LINQ euering:

public static class DataTableExtensions
{
   public static IEnumerable<DataRow> RowsAsEnumerable ( this DataTable source )
        {
            return (source != null) ? source.Rows.OfType<DataRow>() : Enumerable.Empty<DataRow>();
        }
}

then modified my code as below: 然后修改我的代码如下:

//Get IDs to delete
var deleteIds = from r in emails.RowsAsEnumerable()
                 where String.Compare(r["failEmail"].ToString(), "fail", true) == 0
                 select r["itemID"];

//Get all rows to delete
var rows2Delete = (from r in emails.RowsAsEnumerable()
                  where deleteIds.Contains(r["itemID"])
                  select r).ToList();

//Now delete them
foreach (var row in rows2Delete)
    emails.Rows.Remove(row);
emails.AcceptChanges();

and now it works, just wish I could do it the normal way successfully. 现在它的工作原理,希望我能以正常的方式成功地做到这一点。

        foreach (DataRow rowFail in emails.Select("failEmail = 'fail'"))
        {
            DataRow[] rowsItem = emails.Select(String.Format("itemID = '{0}'", rowFail["itemID"]));

            for (int i = rowsItem.Length - 1; i >= 0; i--)
            {
                rowsItem[i].Delete();
            }
        }

        emails.AcceptChanges();

DataTable.Select returns an array of all DataRow objects that match the filter criteria. DataTable.Select返回与筛选条件匹配的所有DataRow对象的数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM