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

NoS*_*ler 3 c# datatable dataset winforms

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

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

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

这种方法的问题是,我只得到属于C3列的值列表.我可以做多一些,如图这里,但话又说回来,我将有一个新的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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

删除行后,我收到错误消息"此行已从表中删除,并且没有任何数据." 我在这里错过了什么?

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

Ser*_*kiy 6

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

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

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

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

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