从另一个数据表中存在的数据表中删除行

时间:2014-02-09 22:39:29

标签: c# winforms datatable dataset

我在DataSet中有一个带有列C1(PK),C2和C3(唯一值)的DataTable dt1,删除了一些行后,我将进行AcceptChanges。我有另一个DataTable dt2,其结构与dtA相同。我想删除dtA中存在于dtB中的行,比较C3(唯一值)并执行AcceptChanges。

我可以达到非常接近,但不是我想做的事情除了以下情况(从here学到的):

var a = dt1.AsEnumerable().Select(r => r.Field<Guid>("C3"));
var b = dt2.AsEnumerable().Select(r => r.Field<Guid>("C3"));
var c = a.Except(b);

这种方法的问题是,我只得到属于C3列的值列表。我可以像here所示做更多的事情,但是我将再次拥有一个新的DataTable,我仍然不会更改现有的dt1表。

我想到的第二种方法是做类似下面的事情:

foreach (DataRow r1 in ds1.Tables[0].Rows)
{
    foreach(DataRow r2 in dt2.Rows)
    {
        if (r1.Field<Guid>("Guid1") == r2.Field<Guid>("Guid2"))
        {
            r1.Delete();
        }
    }
}

这里一旦删除了行,我就会收到一条错误消息“此行已从表中删除且没有任何数据。”我在这里缺少什么?

我也有一种感觉,可能有更好的方法这样做,只是不知道大声笑。

1 个答案:

答案 0 :(得分:5)

  

我收到一条错误消息“此行已从表中删除并且确实已删除   没有任何数据'我在这里缺少什么?

你有两个循环 - 外部和内部。你有两个问题。第一个是找到匹配时删除行。在内循环的下一次迭代中,您试图获取已删除行的值,这将抛出异常。但是即使你在删除行后会破坏内部循环,你也会遇到另一个问题 - 修改你要枚举的行。因此,您的代码应如下所示:

foreach (DataRow r1 in dt1.Rows.Cast<DataRow>().ToArray()) // save rows to array
{
    foreach (DataRow r2 in dt2.Rows)
    {
        if (r1.Field<Guid>("C3") == r2.Field<Guid>("C3"))
        {
            r1.Delete();
            break; // break inner loop
        }
    }
}

但是我会使用LINQ方法 - 通过连接id字段上的行来获取要删除的行,然后从表中删除它们:

var rowsToDelete = from r1 in dt1.AsEnumerable()
                   join r2 in dt2.AsEnumerable()
                        on r1.Field<Guid>("C3") equals r2.Field<Guid>("C3")
                   select r1;

foreach(DataRow row in rowsToDelete.ToArray())
   row.Delete(); // marks row as deleted;

注意:在现有DataRow上使用Delete方法后,其RowState将变为已删除。行仍然是已删除,直到您调用AcceptChanges,从表中删除行。