使用C#比较和删除数据表行:

the*_*van 4 c# linq asp.net datatable visual-studio-2010

我有两个表,如DTTable1和DTTable2.它有以下记录.

DTTable1:

    ItemID     Specification    Amount
   ---------  ---------------  ---------
      1             A             10
      1             B             20
      1             C             30
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

我试过foreach和forloop.使用ForEach:

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

它显示错误,"集合已被修改;枚举操作可能无法执行".所以我使用For Loop,它也没有给出所需的结果.

使用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();
Run Code Online (Sandbox Code Playgroud)

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

    ItemID     Specification    Amount
   ---------  ---------------  ---------
      1             B             20
      2             A             10
      2             B             20
      3             A             10
      3             B             20
Run Code Online (Sandbox Code Playgroud)

怎么解决这个?这样做最简单的方法是什么?

lc.*_*lc. 6

在第一个示例中枚举时,无法修改集合.您应该获取要删除的行的列表,然后删除它们.

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);
Run Code Online (Sandbox Code Playgroud)

或者,使用linq内联:

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

您的第二个示例失败,因为一旦删除了一行,后续行的索引会发生变化,但您会继续增加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);
Run Code Online (Sandbox Code Playgroud)

要么

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++;
}
Run Code Online (Sandbox Code Playgroud)

旁注:我想知道你是否真的想要总是比较第0行的数据,给出你的描述.也许你的意思是比较下面的所有行(尽管不是最优的)?

if (DTTable1.Any(r => DTTable2.Rows[i]["ItemID"].ToString() == r["ItemID"].ToString()))
Run Code Online (Sandbox Code Playgroud)