Eliminar filas específicas de DataTable

Quiero eliminar algunas filas de DataTable, pero da un error como este,

La colección fue modificada; la operación de enumeración podría no ejecutarse

Yo uso para borrar este código,

foreach(DataRow dr in dtPerson.Rows){ if(dr["name"].ToString()=="Joe") dr.Delete(); } 

Entonces, ¿cuál es el problema y cómo solucionarlo? ¿Qué método aconsejas?

Si elimina un elemento de una colección, esa colección ha sido modificada y no puede seguir enumerando a través de ella.

En su lugar, use un bucle For, como por ejemplo:

 for(int i = dtPerson.Rows.Count-1; i >= 0; i--) { DataRow dr = dtPerson.Rows[i]; if (dr["name"] == "Joe") dr.Delete(); } 

Tenga en cuenta que está iterando en sentido inverso para evitar omitir una fila después de eliminar el índice actual.

Antes de que todos salten en el carro de ” No se puede eliminar filas en una enumeración “, primero debe darse cuenta de que las tablas de datos son transaccionales y no purgan los cambios hasta que no llame a AcceptChanges ()

Si está viendo esta excepción al llamar a Eliminar , ya se encuentra en un estado de datos de cambios pendientes . Por ejemplo, si acaba de cargar desde la base de datos, llamar a Delete arrojaría una excepción si estuviera dentro de un bucle foreach.

¡PERO! ¡PERO!

Si carga filas desde la base de datos y llama a la función ‘ AcceptChanges () ‘, confirma todos los cambios pendientes en DataTable. Ahora puede recorrer la lista de filas llamando a Delete () sin ningún cuidado en el mundo, ya que simplemente señala la fila para Deletion, pero no se confirma hasta que vuelva a llamar a AcceptChanges ()

Me doy cuenta de que esta respuesta está un poco pasada de moda, pero tuve que lidiar con un problema similar recientemente y con suerte esto ahorra algo de dolor para un futuro desarrollador que trabaja con un código de 10 años 🙂


Ps Aquí hay un ejemplo de código simple agregado por Jeff :

DO#

 YourDataTable.AcceptChanges(); foreach (DataRow row in YourDataTable.Rows) { // If this row is offensive then row.Delete(); } YourDataTable.AcceptChanges(); 

VB.Net

 ds.Tables(0).AcceptChanges() For Each row In ds.Tables(0).Rows ds.Tables(0).Rows(counter).Delete() counter += 1 Next ds.Tables(0).AcceptChanges() 

con esta solución:

 for(int i = dtPerson.Rows.Count-1; i >= 0; i--) { DataRow dr = dtPerson.Rows[i]; if (dr["name"] == "Joe") dr.Delete(); } 

si vas a utilizar la tabla de datos después de eliminar la fila, obtendrás un error. Entonces, lo que puedes hacer es: reemplazar dr.Delete(); con dtPerson.Rows.Remove(dr);

Esto funciona para mí,

 List lstRemoveColumns = new List() { "ColValue1", "ColVal2", "ColValue3", "ColValue4" }; List rowsToDelete = new List(); foreach (DataRow row in dt.Rows) { if (lstRemoveColumns.Contains(row["ColumnName"].ToString())) { rowsToDelete.Add(row); } } foreach (DataRow row in rowsToDelete) { dt.Rows.Remove(row); } dt.AcceptChanges(); 
 DataRow[] dtr=dtPerson.select("name=Joe"); foreach(var drow in dtr) { drow.delete(); } dtperson.AcceptChanges(); 

Espero que te ayude

O simplemente convierta una colección de filas de DataTable en una lista:

 foreach(DataRow dr in dtPerson.Rows.ToList()) { if(dr["name"].ToString()=="Joe") dr.Delete(); } 

Para eliminar toda la fila de DataTable , haz esto

 DataTable dt = new DataTable(); //User DataTable DataRow[] rows; rows = dt.Select("UserName = 'KarthiK'"); //'UserName' is ColumnName foreach (DataRow row in rows) dt.Rows.Remove(row); 

Dónde está el problema: está prohibido eliminar elementos de la colección dentro de un bucle foreach.

Solución: O lo hace como escribió Widor, o usa dos bucles. En el primer paso sobre DataTable, solo almacena (en una lista temporal) las referencias a las filas que desea eliminar. Luego, en el segundo pase sobre su lista temporal, borre esas filas.

     <%# Container.DataItemIndex + 1 %>          **This is the row binding event** protected void grd_item_list_RowCommand(object sender, GridViewCommandEventArgs e) { item_list_bind_structure(); if (ViewState["item_list"] != null) dt = (DataTable)ViewState["item_list"]; if (e.CommandName == "REMOVE_ITEM") { var RowNum = Convert.ToInt32(e.CommandArgument.ToString()) - 1; DataRow dr = dt.Rows[RowNum]; dr.Delete(); } grd_item_list.DataSource = dt; grd_item_list.DataBind(); } 

Sé que esta es, muy, una vieja pregunta, y tengo una situación similar hace unos días.

El problema fue que en mi mesa son aprox. 10000 filas, por lo que las filas de DataTable través de bucle fueron muy lentas.

Finalmente, encontré una solución mucho más rápida, en la que hago una copia de la DataTable de origen con los resultados deseados, una DataTable origen claro y merge resultados de la DataTable temporal en la fuente uno.

Nota : en su lugar, busque Joe en DataRow llamado name DataRow buscar todos los registros que no tengan el nombre Joe (forma de búsqueda poco opuesta).

Hay un ejemplo ( vb.net ):

 'Copy all rows into tmpTable whose not contain Joe in name DataRow Dim tmpTable As DataTable = drPerson.Select("name<>'Joe'").CopyToTable 'Clear source DataTable, in Your case dtPerson dtPerson.Clear() 'merge tmpTable into dtPerson (rows whose name not contain Joe) dtPerson.Merge(tmpTable) tmpTable = Nothing 

Espero que esta solución más corta ayude a alguien.

Hay código c# (no estoy seguro de que sea correcto porque utilicé el convertidor en línea :():

 //Copy all rows into tmpTable whose not contain Joe in name DataRow DataTable tmpTable = drPerson.Select("name<>'Joe'").CopyToTable; //Clear source DataTable, in Your case dtPerson dtPerson.Clear(); //merge tmpTable into dtPerson (rows whose name not contain Joe) dtPerson.Merge(tmpTable); tmpTable = null; 

Por supuesto, utilicé Try/Catch en caso de que no haya ningún resultado (por ejemplo, si Your dtPerson no contiene el name Joe arrojará una excepción), por lo que no hace nada con Your table, no cambia.

Tengo un conjunto de datos en mi aplicación y fui a establecer cambios (eliminar una fila), pero ds.tabales["TableName"] es de solo lectura. Entonces encontré esta solución.

Es una aplicación wpf C# ,

 try { var results = from row in ds.Tables["TableName"].AsEnumerable() where row.Field("Personalid") == "47" select row; foreach (DataRow row in results) { ds.Tables["TableName"].Rows.Remove(row); } }