web-dev-qa-db-ja.com

DataTable、条件付きで行を削除する方法

私はC#の学習プロセスに携わっており、これまでのところ順調に進んでいます。しかし、私は今、私の最初の「何を言った?」を打った。瞬間。

DataTableは、通常のコレクションの動作だけでなく、DataTable.Selectを通じて、Rowsコレクションへのランダムな行アクセスを提供します。ただし、この機能をDataRow.Deleteに関連付けることはできないようです。これまでのところ、これはテーブルから1つ以上の行を条件付きで削除するために必要なことです。

int max = someDataTable.Rows.Count - 1;
for(int i = max; i >= 0; --i)
{
    if((int)someDataTable.Rows[i].ItemArray[0] == someValue)
    {
        someDataTable.Rows[i].BeginEdit();
        someDataTable.Rows[i].Delete();
    }
    else
        break;
}
someDataTable.AcceptChanges();

しかし、私はこのコードに満足していません。どちらも私は確信していません。私は何かが欠けているに違いない。 1つまたは複数の行を条件付きで削除する必要がある場合、Rowsコレクションを順番にヒットすることを本当に強制されますか?

(逆さまになっても構いません。データテーブルの最後から削除しています。だから大丈夫です)

36
Alexandre Bell

データセットをクエリし、選択した行をループして削除として設定できます。

var rows = dt.Select("col1 > 5");
foreach (var row in rows)
    row.Delete();

...また、簡単にするためにいくつかの拡張メソッドを作成することもできます...

myTable.Delete("col1 > 5");

public static DataTable Delete(this DataTable table, string filter)
{
    table.Select(filter).Delete();
    return table;
}
public static void Delete(this IEnumerable<DataRow> rows)
{
    foreach (var row in rows)
        row.Delete();
}
69
Matthew Whited

LINQを使用し、選択文字列の実行時評価を回避するワンライナーを次に示します。

someDataTable.Rows.Cast<DataRow>().Where(
    r => r.ItemArray[0] == someValue).ToList().ForEach(r => r.Delete());
37
Alain

これを試すのに便利なウィンドウボックスはありませんが、DataViewを使用して次のようなことができると思います。

DataView view = new DataView(ds.Tables["MyTable"]);
view.RowFilter = "MyValue = 42"; // MyValue here is a column name

// Delete these rows.
foreach (DataRowView row in view)
{
  row.Delete();
}

ただし、これはテストしていません。試してみてください。

8
itsmatt

Linqに基づいた拡張方法

public static void DeleteRows(this DataTable dt, Func<DataRow, bool> predicate)
{
    foreach (var row in dt.Rows.Cast<DataRow>().Where(predicate).ToList())
        row.Delete();
}

次に使用します:

DataTable dt = GetSomeData();
dt.DeleteRows(r => r.Field<double>("Amount") > 123.12 && r.Field<string>("ABC") == "XYZ");
0
Sebastian Widz