DataSetに列C1(PK)、C2、およびC3(一意の値)を持つDataTable dt1があり、いくつかの行を削除した後、AcceptChangesを実行します。dtAと構造が同じである別のDataTabledt2があります。C3(一意の値)で比較したdtBに存在するdtAの行を削除し、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);
このアプローチの問題は、C3列に属する値のリストのみを取得していることです。ここに示すように、さらにいくつかのことを行うことができますが、新しいDataTableが作成され、既存のdt1テーブルは変更しません。
私が考えた2番目のアプローチは、次のようなことをすることでした。
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();
}
}
}
ここで、行が削除されるとすぐに、「この行はテーブルから削除され、データがありません」というエラーが表示されます。ここで何が欠けていますか?
私はまた、これを行うためのより良い方法があるかもしれないと感じています、ただ笑を知りません。
「この行はテーブルから削除され、データがありません」というエラーが表示されます。ここで何が欠落していますか?
外側と内側の2つのループがあります。そして、ここには2つの問題があります。1つ目は、一致が見つかったときに行を削除することです。内部ループの次の反復で、削除された行の値を取得しようとしていますが、これにより例外がスローされます。ただし、行を削除した後に内部ループを中断したとしても、別の問題が発生します。列挙している行の変更です。したがって、コードは次のようになります。
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;
注:Delete
既存のDataRowでメソッドを使用すると、そのRowStateはDeletedになります。を呼び出すまで行は削除されたままになりAcceptChanges
ます。これにより、テーブルから行が削除されます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加