2009-10-19 81 views
35

Estoy involucrado en un proceso de aprendizaje de C# y va bien hasta ahora. Sin embargo, ahora mismo toco mi primer "¿decir qué?" momento.DataTable, cómo eliminar condicionalmente las filas

DataTable ofrece acceso de fila aleatorio a su colección de filas, no solo a través del comportamiento de colecciones típicas, sino también a través de DataTable.Select. Sin embargo, parece que no puedo vincular esta capacidad con DataRow.Delete. Hasta ahora esto es lo que parece que necesito 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 satisfecho con este código. Ni estoy convencido. Debo estar perdiendo algo. ¿De verdad me veo obligado a presionar secuencialmente la colección Filas si necesito eliminar una o más filas de forma condicional?

(no les importa la invertida para. Estoy borrando desde el final de la tabla de datos. Así que está bien)

Respuesta

66

Se puede consultar la base de datos y luego bucle de las filas seleccionadas para establecer como borrado.

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

... y también se podría crear algunos métodos de extensión para que sea 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(); 
} 
+0

Ah! No se me ocurrió seleccionar() devolvería una referencia a las filas de tablas de datos. Sabía que tenía que estar perdiendo algo. ¡Gracias un montón! –

+0

Demasiado buena solución, esto también resolvió mi problema de datatable.select cambiando el orden. – Signcodeindie

+0

Gran solución Matthew – Ravia

8

no tengo una ventana de caja a mano para tratar de esto, pero creo que se puede utilizar un DataView 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. Puede intentarlo.

+0

Lo intenté y funcionó. Sin embargo, prefiero el enfoque Select. Pero es bueno tenerlo en cuenta. Gracias :) +1 –

35

Aquí hay una sola línea usando LINQ y evitando cualquier evaluación en tiempo de ejecución de seleccionar cadenas: Método

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

Me gustó mucho esta solución, muy agradable, ¡gracias! – MDV2000

+2

En algún momento, recuerda llamar a la función someDataTable.AcceptChanges(); después de eliminar –

+1

@GreyWolf, si desea volver a escribir los cambios en la base de datos, ¡NO llame a AcceptChanges! AcceptChanges marcará todas las filas nuevas/actualizadas como sin cambios, por lo tanto, DataAdapter pensará que NO hay cambios y no escribirá nada en la base de datos en .Update(). –

0

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

A continuación, utilice:

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