【问题标题】:Compare and delete datatable row using C#:使用 C# 比较和删除数据表行:
【发布时间】:2012-10-10 05:29:23
【问题描述】:

我有两个表,例如 DTTable1 和 DTTable2。有以下记录。

DTTable1:

    ItemID     Specification    Amount
   ---------  ---------------  ---------
      1             A             10
      1             B             20
      1             C             30

DTTable1:

    ItemID     Specification    Amount
   ---------  ---------------  ---------
      1             A             10
      1             B             20
      1             C             30
      2             A             10
      2             B             20
      3             A             10
      3             B             20

这里我想比较这两个表。如果 DTTable2 中存在 DTTable1 记录(仅考虑 ItemID),则删除 ItemID 与 DTTable1 相同的相应行。

我已经尝试过 foreach 和 forloop。 使用 ForEach:

   foreach (DataRow DR in DTTable2.Rows)
   {
      if (DR["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString())
      {
           DTTable2.Rows.Remove(DR);                            
      }
   }
   DTTable2.AcceptChanges();

它显示了错误, “集合已修改;枚举操作可能无法执行”。所以我使用了 For 循环,它也没有给出想要的结果。

使用 For 循环:

   for (int i = 0; i < DTTable2.Rows.Count; i++)
   {
       if (DTTable2.Rows[i]["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString())
       {
           DTTable2.Rows.RemoveAt(i);
       }
   }
   DTTable2.AcceptChanges();

但有时,第二行不会从表格中删除。我得到最终的 DataTable 为

    ItemID     Specification    Amount
   ---------  ---------------  ---------
      1             B             20
      2             A             10
      2             B             20
      3             A             10
      3             B             20

如何解决这个问题?最简单的方法是什么?

【问题讨论】:

  • 您是否从数据库中选择这些记录,如果是,我可以帮助您进行查询,该查询将仅选择所需的记录,因为使用 sql 完成它的效率要高得多

标签: c# asp.net visual-studio-2010 linq datatable


【解决方案1】:

您不能像在第一个示例中那样在枚举集合时修改它。您应该获取要删除的行列表,然后将其删除。

List<DataRow> rowsToDelete = new List<DataRow>();
foreach (DataRow DR in DTTable2.Rows)
{
    if (DR["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString())
        rowsToDelete.Add(DR);           
}

foreach (var r in rowsToDelete)
    DTTable2.Rows.Remove(r);

或者,使用 linq 内联:

DTTable2.Rows
    .Where(DR => DR["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString())
    .ToList()
    .ForEach(r => DTTable2.Rows.Remove(r));

您的第二个示例失败,因为一旦删除了一行,后续行的索引就会更改,但您会继续增加 i,这实际上会跳过紧跟已删除行的行。有两种解决方法:

for (int i = DTTable2.Rows.Count - 1; i >= 0; i--)
    if (DTTable2.Rows[i]["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString())
        DTTable2.Rows.RemoveAt(i);

或者

int i = 0;
while (i < DTTable2.Rows.Count)
{
    if (DTTable2.Rows[i]["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString())
        DTTable2.Rows.RemoveAt(i);
    else
        i++;
}

旁注:根据您的描述,我想知道您是否真的要始终与 第 0 行的 数据进行比较。也许您打算像下面这样比较所有行(尽管根本不是最佳的)?

if (DTTable1.Any(r => DTTable2.Rows[i]["ItemID"].ToString() == r["ItemID"].ToString()))

【讨论】:

    【解决方案2】:

    尝试使用:

    var list = DTTable2.Rows.ToList();//create new list of rows
    foreach (DataRow DR in list)
    {
        //if bla bla bla
        DTTable2.Rows.Remove(DR);
    }
    

    【讨论】:

      【解决方案3】:

      你可以使用LINQ to DataTable

      var result =  DTTable1.AsEnumerable()
                         .Where(row => !DTTable2.AsEnumerable()
                                               .Select(r => r.Field<int>("ItemID"))
                                               .Any(x => x == row.Field<int>("ItemID"))
                        ).CopyToDataTable();
      

      【讨论】:

        【解决方案4】:

        好吧,伙计们。我的情况几乎相同,无论我如何尝试,我一直遇到问题。我的解决方案是根本不尝试遍历 DataTable。我从第一个 DataTable 中创建了一个数组(其中包含需要从第二个 DataTable 中删除的行)。遍历 Array 并使用 select 删除 DataTable 中匹配的行。由于它不是循环,并且它可以匹配 DataTable 中的任何行,所以我不再遇到错误。

        注意:原始 DataTable 是一个单列表,其中包含您尝试按行从第二个 DataTable 中删除的内容(不管它有多少列)。将“LinkName=”替换为 1 列表的列名。

         public DataTable RemoveDuplicateRows(DataTable OriginalLinks, DataTable UpdatedLinks) // OriginalLinks is a 1-col dt to delete from new dt
            {
        
                ArrayList arrOriginalLinks = new ArrayList();
        
                if (OriginalLinks.Rows.Count > 0)
                {
        
                    foreach (DataRow dr in OriginalLinks.Rows)
                    {
                        arrOriginalLinks.Add(dr["LinkName"]);
                    }
                }
        
        
                if (OriginalLinks.Rows.Count == 0)
                {
                    // do nothing
                }
                else
                {
                    for (int i = OriginalLinks.Rows.Count - 1; i >= 0; i--)
                    {
                        string filter = "LinkName='" + arrOriginalLinks[i].ToString() + "'";
        
                        UpdatedLinks.Select(filter).ToList().ForEach(r => r.Delete());
        
        
                    }
        
                }
        
                return UpdatedLinks;
        
            }
        

        这将返回第二个 DataTable,其中只剩下与第一个 DataTable 中的值不匹配的行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-01
          • 1970-01-01
          • 2014-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多