name - get field from datarow c#
EliminaciĆ³n segura de DataRow en ForEach (15)
No entiendo por qué este código no funciona.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
Donde los artículos tienen un Count
, esto es lo que he hecho:
int Count = myTable.Rows.Count;
while (Count > 0) // replace condition with myTable.Rows.Count if unconditionally performed on all rows
{
DataRow row = myTable.Rows[0] // or however you want to find your index
// do some work
myTable.Rows.Remove(row);
// if you want to perform a check to break out of while
if (someCondition)
Count = 0;
else
Count = myTable.Rows.Count;
}
Tenga en cuenta que, cuando los objetos tienen una colección .GetXXXX()
, como FileInfo
(IIRC), la eliminación de los contenidos del elemento en un foreach
es aceptable. Una solución que he considerado es la creación de un método de extensión que proporciona un método .GetItems()
.
El contenido de Rows
cambia mientras está iterando si elimina una fila, lo que hace que la iteración no sea válida.
Sin embargo, puede copiar las filas en una colección primero y luego iterar sobre la colección y eliminar las filas de esa manera. Esto asegura que la iteración no se interrumpa cambiando los datos que se iterarán.
Esto se aplica a prácticamente cualquier colección. Si intenta eliminar un elemento mientras recorre la colección, tendrá un problema. Por ejemplo, si elimina la fila 3, la fila anterior 4 se convierte en la fila 3.
Esto se debe a que parece que intentas desmontar la escalera de la escalera que subes. Simplemente, no puedes eliminar un elemento que iteras.
Por lo tanto, debe usar una matriz diferente para iterar y eliminarla de la propiedad Rows
tabla de datos.
foreach (DataRow dataRow in dataTable.Select())
{
if (true)
{
dataTable.Rows.Remove(dataRow);
}
}
Hay otra versión (creo que es más fácil) que acabo de usar:
int i=0;
while (i < myDataTable.Rows.Count)
{
if (condition) //should it be deleted?
myDataTable.Rows.RemoveAt(i);
else
i++;
}
Esto más rápido.
La forma más fácil de lograr esto es usar una lista para asignar las filas que desea eliminar y luego eliminar las filas fuera de la iteración de DataTable.
DO#
List<DataRow> rowsWantToDelete= new List<DataRow>();
foreach (DataRow dr in dt.Rows)
{
if(/*Your condition*/)
{
rowsWantToDelete.Add(dr);
}
}
foreach(DataRow dr in rowsWantToDelete)
{
dt.Rows.Remove(dr);
}
VB
Dim rowsWantToDelete As New List(Of DataRow)
For Each dr As DataRow In dt
If ''Your condition'' Then
rowsWantToDelete .Add(dr)
End If
Next
For Each dr As DataRow In rowsWantToDelete
dt.Rows.Remove(dr)
Next
La mayoría de las colecciones en .NET no le permiten cambiar el contenido de la colección mientras lo itera. De los documentos para IEnumerator
:
Un enumerador sigue siendo válido siempre que la colección permanezca sin cambios. Si se realizan cambios en la colección, como agregar, modificar o eliminar elementos, el enumerador queda irrevocablemente invalidado y la siguiente llamada a MoveNext o Reset arroja una InvalidOperationException. Si la colección se modifica entre MoveNext y Current, Current devuelve el elemento que está configurado, incluso si el enumerador ya está invalidado.
La mejor solución suele ser crear una colección separada (por ejemplo, una List<DataRow>
) de los elementos que desea eliminar, y luego eliminarlos después de que haya terminado de iterar.
Manera más segura - use for
loop
for (int i = datatable.Rows.Count - 1; i >= 0; i--)
{
if (true)
{
datatable.Rows[i].Delete();
}
}
No olvides AcceptChanges
para eliminar todas las filas marcadas:
datatable.AcceptChanges();
No puede modificar una colección mientras la itera usando una declaración foreach
.
puedes probar algo como eso:
List<DataRow> deletedRows = new List<DataRow>();
foreach (DataRow dataRow in dataTable.Rows)
{
if(true) deletedRows.Add(dataRow);
}
foreach(DataRow dataRow in deletedRows)
{
dataRow.Delete();
}
Puede ser que mi respuesta ya no sea útil. el lanzamiento de excepción en Foreach con DataRow solo aparece en .Net 2.0 y versiones anteriores, el motivo es la descripción en msdn http://msdn.microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx
Si se agrega el RowState de la fila, la fila se elimina de la tabla.
RowState se elimina después de utilizar el método Delete. Permanece eliminado hasta que llame a AcceptChanges.
Una fila eliminada se puede recuperar invocando Rechazar Cambios.
para pasar este problema puede llamar a DataTable.AcceptChanges () antes de usar foreach
Seguro Magents
Así es como lo hice y funciona bien
dt = GetStationeryConsolidationDetails(txtRefNo.Text);
int intRows = dt.Rows.Count;
int x = 0;
for (int c = 0; c < intRows; c++)
{
if (dt.Rows[c - x]["DQTY"].ToString() == "0")
{
dt.Rows[c - x].Delete();
dt.AcceptChanges();
x++;
}
}
Si llama al método de eliminación, solo tiene que llamar a AcceptChanges()
en la tabla que está modificando, después del bucle foreach.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
El método de eliminación simplemente marca la fila para eliminar.
http://msdn.microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx
Solo para las personas que buscan un escenario específico como yo, necesitaba acortar el tiempo empleado, y una vez que se extrae información útil de cada fila, excluí la fila marcando como eliminada.
Espero que esto ayude a alguien ...
foreach (DataRow dataRow in dataTable.Rows)
{
if (dataRow.RowState != DataRowState.Deleted)
{
if (your condition here)
{
dataRow.Delete();
}
}
}
Utilizar esta:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
Por favor refiérase a las fotos para entender el funcionamiento de la misma.
- Simplemente eliminado pero no eliminado de la DataTable.
- Punto de ruptura antes de la función AcceptChanges ().
- Después de la función Eexecuting AcceptChanges ().
Espero que este problema se resuelva ahora.