DataTable, Cómo eliminar filas condicionalmente


Estoy involucrado en un proceso de aprendizaje de C# y hasta ahora va bien. Sin embargo, acabo de golpear mi primera " decir qué?" momento.

DataTable ofrece acceso aleatorio a su colección de filas, no solo a través del comportamiento típico de las colecciones, sino también a través de DataTable.Seleccionar. Sin embargo, parece que no puedo vincular esta capacidad a DataRow.Eliminar. Hasta ahora esto es lo que parece que tengo que hacer para eliminar condicionalmente una o más filas de una tabla.

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();

Pero no estoy feliz con este código. Tampoco estoy convencido. Debo estar perdiendo algo. ¿Estoy realmente obligado a golpear la colección de filas secuencialmente si necesito eliminar una o más filas condicionalmente?

(no importa el invertido para. Estoy borrando del final de la datatable. Así que está bien)

Author: Alexandre Bell, 2009-10-20

4 answers

Puede consultar el conjunto de datos y, a continuación, hacer un bucle en las filas seleccionadas para configurarlas como eliminar.

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

... y también podría crear algunos métodos de extensión para hacerlo más fácil ...

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();
}
 68
Author: Matthew Whited,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-20 00:19:19

Aquí hay una línea usando LINQ y evitando cualquier evaluación en tiempo de ejecución de cadenas seleccionadas:

someDataTable.Rows.Cast<DataRow>().Where(
    r => r.ItemArray[0] == someValue).ToList().ForEach(r => r.Delete());
 36
Author: Alain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-07 19:38:10

No tengo un cuadro de Windows a mano para probar esto, pero creo que puedes usar una vista de datos y hacer algo así:

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();
}

No he probado esto, sin embargo. Podrías intentarlo.

 8
Author: itsmatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-20 00:23:18

Método de extensión basado en 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();
}

Luego use:

DataTable dt = GetSomeData();
dt.DeleteRows(r => r.Field<double>("Amount") > 123.12 && r.Field<string>("ABC") == "XYZ");
 0
Author: Sebastian Widz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-08 12:47:19