¿Una forma sencilla de copiar o clonar un DataRow?

118

Estoy buscando una forma sencilla de hacer un clon de un DataRow. Es como tomar una instantánea de esa fila y guardarla. Los valores de la Fila original son libres de cambiar, pero todavía tenemos otra copia guardada que no cambia. ¿Es esta la forma correcta de hacerlo?

DataRow Source, Destination;
// Assume we create some columns and fill them with values
Destination.ItemArray = Source.ItemArray;

¿Esto solo establecerá la referencia ItemArray de Snapshot para que apunte a la que está en Fuente o realmente hará una copia separada? ¿Debería hacer esto en su lugar?

Destination.ItemArray = Source.ItemArray.Clone();

EDITAR: No creo que el segundo fragmento de código se compile realmente.

Paul Matthews
fuente
No estoy seguro de entenderlo, ¿desea copiar una fila de datos de una tabla a otra? Si es así, creo que usar DataTable.ImportRow es lo que busca.
Mo Patel
Ok, veo que mi pregunta necesita ser reelaborada ahora
Paul Matthews
2
Tenga en cuenta que, en algunos escenarios, es posible que no necesite hacer esto porque la cadena de datos en sí admite la edición transaccional con BeginEdit / EndEdit / CancelEdit; también puede llamar .RejectChanges en él.
peterG

Respuestas:

185

Puede usar el ImportRowmétodo para copiar Row de DataTable a DataTable con el mismo esquema:

var row = SourceTable.Rows[RowNum];
DestinationTable.ImportRow(row);

Actualizar:

Con su nueva edición, creo:

var desRow = dataTable.NewRow();
var sourceRow = dataTable.Rows[rowNum];
desRow.ItemArray = sourceRow.ItemArray.Clone() as object[];

trabajará

cuongle
fuente
Aparentemente, Clone () solo proporciona una copia superficial. ¿Crees que será suficiente para crear una copia idéntica o se requiere un clon profundo?
Paul Matthews
5
@PaulMatthews: Afortunadamente, DataTable contiene tipos de valor, no tipo de referencia, por lo que la copia superficial en el tipo de valor es igual con la copia profunda
cuongle
16
Para las personas que encuentren esta publicación, agregaré lo siguiente, ya que me han preguntado con frecuencia, así que supongo que otras personas podrían estar confundidas. Clonar, copiar solo la estructura, copiar, copiar la estructura y luego los datos. Se dice que otra manera fácil de copiar datos una vez que se han creado instancias de ambas tablas es crear una nueva fila en la tabla de destino y usar lo siguiente: destRow.ItemArray = sourceRow.ItemArrayluego, simplemente agregue la fila nuevamente condestTable.Rows.Add(destRow);
Franck
1
Estoy tratando de usar este método para obtener un clon de una fila de datos. Hago los siguientes pasos, luego borro la tabla de datos que contiene la fila de origen y ahora tengo una fila de origen con campos en blanco.
Sergеу Isupov
Descubrí que usar el método ImportRow funcionó para mí, mientras que el método NewRow no.
OldDog
2

Nota: la respuesta helfpul de Cuongle tiene todos los ingredientes, pero la solución se puede simplificar (no es necesario .ItemArray) y se puede reformular para que coincida mejor con la pregunta tal como se hizo.

Para crear un clon (aislado) de una System.Data.DataRowinstancia determinada , puede hacer lo siguiente:

// Assume that variable `table` contains the source data table.

// Create an auxiliary, empty, column-structure-only clone of the source data table.
var tableAux = table.Clone();
// Note: .Copy(), by contrast, would clone the data rows also.

// Select the data row to clone, e.g. the 2nd one:
var row = table.Rows[1];

// Import the data row of interest into the aux. table.
// This creates a *shallow clone* of it.
// Note: If you'll be *reusing* the aux. table for single-row cloning later, call
//       tableAux.Clear() first.
tableAux.ImportRow(row);

// Extract the cloned row from the aux. table:
var rowClone = tableAux.Rows[0];

Nota: Se realiza una clonación superficial , que funciona tal cual con valores de columna que son instancias de tipo de valor , pero se necesitaría más trabajo para crear también copias independientes de valores de columna que contengan instancias de tipo de referencia (y crear tales copias independientes no siempre es posible ).

mklement0
fuente
1

Parece que no desea mantener todo el DataTable como una copia, porque solo necesita algunas filas, ¿verdad? Si tiene una creteria que puede especificar con una selección en la tabla, puede copiar solo esas filas a una matriz de respaldo adicional de DataRow como

DataRow[] rows = sourceTable.Select("searchColumn = value");

La función .Select () tiene varias opciones y esta, por ejemplo, se puede leer como SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Luego, puede importar las filas que desee como se describe anteriormente.

targetTable.ImportRows(rows[n])

... para cualquier n válida que desee, pero las columnas deben ser las mismas en cada tabla.

¡Algunas cosas que debe saber sobre ImportRow es que habrá errores durante el tiempo de ejecución al usar claves primarias!

Primero quería verificar si ya existía una fila que también fallaba debido a que faltaba una clave primaria, pero luego la verificación siempre fallaba. Al final, decidí borrar las filas existentes por completo e importar las filas que quería nuevamente.

El segundo problema ayudó a comprender lo que sucede. La forma en que estoy usando la función de importación es duplicar filas con una entrada intercambiada en una columna. Me di cuenta de que siempre cambiaba y aún era una referencia a la fila de la matriz. Primero tuve que importar el original y luego cambiar la entrada que quería.

La referencia también explica los errores de clave principal que aparecieron cuando intenté importar la fila por primera vez, ya que realmente se duplicó.

Bolle
fuente
-4

Pero para asegurarse de que se pueda acceder a su nueva fila en la nueva tabla, debe cerrar la tabla:

DataTable destination = new DataTable(source.TableName);
destination = source.Clone();
DataRow sourceRow = source.Rows[0];
destination.ImportRow(sourceRow);
rdjabarov
fuente
3
¿Cuál es el punto de la primera línea de código si la segunda línea de código reasigna la variable?
Erik Philips
Esta respuesta podría necesitar más explicación (y no sé qué significa la necesidad de cerrar la tabla ) y @ErikPhilips tiene un punto ( DataTable destination = source.Clone()debería hacerlo), pero de lo contrario, esta respuesta está perfectamente bien e incluso es preferible al .ItemArrayenfoque en la respuesta aceptada.
mklement0