web-dev-qa-db-ja.com

DataTableの複数の行を削除する方法は?

カスタム条件に適合するDataTable行のループ内の特定のDataRowsを削除するにはどうすればいいですか? (LINQを使用しない場合)

ありがとう

30
pencilCake

「delete」の意味によって異なります

それらを削除済みとしてマークする場合、ループ内で訪問するときに各行でDelete()メソッドを呼び出すだけです。次に、データテーブルでAcceptChanges()を呼び出して、削除を完了させる必要があります-おそらくデータベースを更新した後(関係する場合)。

foreach( DataRow row in someTable.Rows )
{
    if( /* your condition here */ )
        row.Delete();
}
someTable.AcceptChanges();

DataTableから削除する場合は、2つのパスで削除する必要があります:

List<DataRow> rowsToDelete = new List<DataRow>();
foreach( DataRow row in someTable.Rows )
{
    if( /* your condition here */ )
    {
        rowsToDelete.Add( row );
    }
}

foreach( DataRow row in rowsToDelete )
{
    someTable.Rows.Remove( row );
}

行を削除するには、常に最初の方法を使用できることに注意してください-行をDeletedとしてマークしてから変更を受け入れると、テーブルから自動的に削除されます。ただし、DataRowコレクションからRowsオブジェクトを単純に削除する方がより明確で効率的な場合があります。

57
LBushkin

この例のようなものを試してください

DataTable table = new DataTable();
table.Columns.Add("Foo",typeof(int));
for (int i = 0; i < 10; i++)
    table.Rows.Add(i);

for (int i = table.Rows.Count -1; i >=0; i--)
{
    // sample removes all even foos
    if ((int)table.Rows[i]["Foo"] % 2 == 0)
        table.Rows.RemoveAt(i);
}
9
Anthony Pegram

他の方法は

    DataRow[] DrArrCheck = DataTableName.Select("ID > 0");
    foreach(DataRow DrCheck in DrArrCheck)
    {
        DataTableName.Rows.Remove(DrCheck);
    }
4
BharathiNathan

上記で提案されているものよりも短い解決策が必要な場合は、結果のリストをループして、sub(x)のようなlambdaを使用してみてください。これらの各行を削除します。

dt.Select("Column1 > 0").ToList.ForEach(Sub(x) dt.Rows.Remove(x))
4
Sergey

複数の行(たとえば、100,000から50,000)を削除するには、datatable.Rows.Remove(row)またはrow.Delete()を実行するよりも、データベースをコピーする方がはるかに高速です。例えば:

DataRow[] rowsToKeep = datatable.Select("ID > 50000");
DataTable tempDataTable= rowsToKeep.CopyToDataTable;
dataTable.Clear();
dataTable.Merge(tempDataTable);
tempDataTable.Dispose();
1
tval
 public static void DeleteRowsFromDataTable(DataTable dataTable, string columnName, string columnValue)
        {
            IEnumerable<DataRow> dataRows = (from t in dataTable.AsEnumerable()
                                             where t.Field<string>(columnName) == columnValue
                                             select t);
            foreach (DataRow row in dataRows)
                dataTable.Rows.Remove(row);
        }
1
Vin

select()の結果を反復処理してみてください。これは他の回答とかなり似ていますが、最も直接的なものだと思います

DataRow[] r = table.Select();
for (int i = 0; i < r.Length; i++)
{
    if (i % 2 == 0)
        r[i].Delete();
}
0
Kleinux

私は常にLBushkinの「2フェーズ」アプローチを使用し、そのための関数を記述することは最終的に価値があると判断しました。

    public delegate bool DataRowComparer(DataRow dr);

    public static void RemoveDataRows(DataTable table, DataRowComparer drc)
    {
        List<DataRow> RowsToRemove = new List<DataRow>();
        foreach (DataRow dr in table.Rows)
            if (drc(dr))
                RowsToRemove.Add(dr);
        foreach (DataRow dr in RowsToRemove)
            table.Rows.Remove(dr);
    }

そして今、私は1行のコードで行を削除できます(たとえば):

RemoveDataRows(dt, row => row["StringVal"].ToString() == "B" && (Int16)(row["NumberVal"]) >= 4);

これが誰にも役立つ場合...

(さらに短縮する方法はありがたいです。)

0
user2524845