Un modo semplice per copiare o clonare un DataRow?


118

Sto cercando un modo semplice per creare un clone di un DataRow. Un po 'come fare un'istantanea di quella riga e salvarla. I valori della riga originale sono quindi liberi di cambiare ma abbiamo ancora un'altra copia salvata che non cambia. È questo il modo corretto per farlo?

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

Questo imposterà semplicemente il riferimento ItemArray di Snapshot in modo che punti a quello in Source o in realtà ne farà una copia separata? Dovrei farlo invece?

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

EDIT: non credo che il secondo frammento di codice venga effettivamente compilato.


Non sono sicuro di aver capito, vuoi copiare un datarow da un tavolo a un altro tavolo? Se è così, credo che usare DataTable.ImportRow sia ciò che stai cercando.
Mo Patel

Ok, vedo che la mia domanda deve essere rielaborata ora
Paul Matthews

2
Nota che in alcuni scenari potresti non aver bisogno di farlo perché il datarow stesso supporta l'editing transazionale con BeginEdit / EndEdit / CancelEdit; inoltre puoi chiamare .RejectChanges su di esso.
peterG

Risposte:


185

È possibile utilizzare il ImportRowmetodo per copiare Row da DataTable a DataTable con lo stesso schema:

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

Aggiornare:

Con la tua nuova modifica, credo:

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

funzionerà


Apparentemente Clone () fornisce solo una copia superficiale. Pensi che sarà sufficiente per creare una copia identica o è necessario un clone profondo?
Paul Matthews

5
@PaulMatthews: Fortunatamente DataTable contiene i tipi di valore, non il tipo di riferimento, quindi la copia superficiale nel tipo di valore è lo stesso con la copia profonda
cuongle

16
Per le persone che trovano questo post aggiungerò quanto segue come mi è stato chiesto spesso, quindi immagino che altre persone potrebbero essere confuse. Clona copia solo la struttura, Copia copia la struttura e poi i dati. Detto questo, un altro modo semplice per copiare i dati una volta che entrambe le tabelle sono state istanziate è creare una nuova riga nella tabella di destinazione e utilizzare quanto segue: destRow.ItemArray = sourceRow.ItemArrayquindi aggiungere semplicemente la riga condestTable.Rows.Add(destRow);
Franck

1
Sto cercando di utilizzare questo metodo per ottenere un clone di un datarow. Faccio i seguenti passaggi, quindi cancello il datatable che contiene la riga di origine e ora ho una riga di origine con campi vuoti.
Sergеу Isupov

Ho scoperto che l'utilizzo del metodo ImportRow ha funzionato per me, mentre il metodo NewRow no.
OldDog

2

Nota: la risposta helfpul di cuongle ha tutti gli ingredienti, ma la soluzione può essere semplificata (non è necessario .ItemArray) e può essere riformulata per soddisfare meglio la domanda come chiesto.

Per creare un clone (isolato) di una determinata System.Data.DataRowistanza , puoi eseguire le seguenti operazioni:

// 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: viene eseguita la clonazione superficiale , che funziona così com'è con i valori di colonna che sono istanze di tipo valore , ma sarebbe necessario più lavoro per creare anche copie indipendenti dei valori di colonna contenenti istanze del tipo di riferimento (e la creazione di tali copie indipendenti non è sempre possibile ).


1

Sembra che tu non voglia conservare l'intero DataTable come copia, perché hai solo bisogno di alcune righe, giusto? Se hai un criterio che puoi specificare con una selezione sulla tabella, puoi copiare solo quelle righe in un array di backup extra di DataRow come

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

La funzione .Select () ha diverse opzioni e questa, ad esempio, può essere letta come SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Quindi puoi importare le righe che desideri come descritto sopra.

targetTable.ImportRows(rows[n])

... per qualsiasi n valido che ti piace, ma le colonne devono essere le stesse in ogni tabella.

Alcune cose che dovresti sapere su ImportRow sono che ci saranno errori durante il runtime quando usi le chiavi primarie!

Per prima cosa volevo verificare se esisteva già una riga che non è riuscita a causa di una chiave primaria mancante, ma poi il controllo è sempre fallito. Alla fine ho deciso di cancellare completamente le righe esistenti e importare di nuovo le righe che volevo.

La seconda questione ha aiutato a capire cosa succede. Il modo in cui utilizzo la funzione di importazione consiste nel duplicare le righe con una voce scambiata in una colonna. Mi sono reso conto che cambiava sempre ed era ancora un riferimento alla riga nell'array. Ho dovuto prima importare l'originale e poi modificare la voce che volevo.

Il riferimento spiega anche gli errori della chiave primaria che sono comparsi quando ho provato a importare per la prima volta la riga poiché era davvero raddoppiata.


-4

Ma per assicurarti che la tua nuova riga sia accessibile nella nuova tabella, devi chiudere la tabella:

DataTable destination = new DataTable(source.TableName);
destination = source.Clone();
DataRow sourceRow = source.Rows[0];
destination.ImportRow(sourceRow);

3
Qual è il punto della prima riga di codice se la seconda riga di codice riassegna la variabile?
Erik Philips

Questa risposta potrebbe usare più spiegazioni (e non so cosa significhi chiudere la tabella ) e @ErikPhilips ha un punto ( DataTable destination = source.Clone()dovrebbe fare), ma per il resto questa risposta è perfettamente a posto e persino preferibile .ItemArrayall'approccio nella risposta accettata.
mklement0
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.