【问题标题】:deleting rows from datatable causes error从数据表中删除行会导致错误
【发布时间】:2014-05-02 17:00:17
【问题描述】:

我正在尝试从DataTable 中删除不需要的行。基本上,可能有几行itemID 是相同的。我想找到"failEmail" = "fail" 列所在的行,并使用这些行的itemID,从电子邮件DataTable 中删除所有具有相同itemID 的行。

这是我尝试过的:

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

这是我在第二遍时收到的错误消息:

此行已从表中删除,并且没有任何数据。 BeginEdit() 将允许在该行中创建新数据

我怎样才能做我需要做的而不抛出这样的错误?有没有更好的方法比如使用LiNQ 查询?

【问题讨论】:

  • 简单地调用 delete 方法会起作用吗?比如:emails.rows[0].delete();?
  • 另外,如果这是您的代码的复制/粘贴,那么您在这一行中有一个错误的括号:emails.Rows.RemovedDrCheck); 要么删除它,要么添加左括号,使其显示为 emails.Rows.RemovedDrCheck();
  • @armadadrive 问题是最初只有几行有fail,我需要获取这些行的itemID,然后选择所有这些...

标签: c# linq datatable


【解决方案1】:

问题在于,当同一个 itemID 有多个“失败”条目时,您会尝试多次删除它们。

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

【讨论】:

  • 我的代码出现“System.NullReferenceException”异常 - 即使数据表中有记录,并且记录与选择匹配
【解决方案2】:

根据我从 MSDN c# 论坛得到的答案,这就是我最终要做的:

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

然后修改我的代码如下:

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

现在它可以工作了,只是希望我能以正常的方式成功。

【讨论】:

    【解决方案3】:
            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 返回一个包含所有符合过滤条件的 DataRow 对象的数组。

    【讨论】:

    • 你能解释一下你的答案吗
    • 问题是emailsdatatable 中只有几行最初会有fail,我需要获取这些行的 itemID,然后选择与这些 itemID 匹配的所有行。 .
    猜你喜欢
    • 2020-11-28
    • 2021-07-25
    • 2022-11-13
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-15
    • 2022-11-14
    相关资源
    最近更新 更多