Einfache Möglichkeit, eine DataRow zu kopieren oder zu klonen?


118

Ich suche nach einer einfachen Möglichkeit, einen Klon einer DataRow zu erstellen. Ein bisschen wie ein Schnappschuss dieser Zeile zu machen und sie zu speichern. Die Werte der ursprünglichen Zeile können dann geändert werden, aber wir haben noch eine andere gespeicherte Kopie, die sich nicht ändert. Ist das der richtige Weg?

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

Wird dadurch nur die ItemArray-Referenz von Snapshot so eingestellt, dass sie auf die in Source verweist, oder wird tatsächlich eine separate Kopie erstellt? Soll ich das stattdessen tun?

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

EDIT: Ich glaube nicht, dass das zweite Code-Snippet tatsächlich kompiliert wird.


Ich bin mir nicht sicher, ob ich verstehe, dass Sie eine Datenzeile von einer Tabelle in eine andere Tabelle kopieren möchten. Wenn ja, glaube ich, dass Sie DataTable.ImportRow verwenden, wonach Sie suchen.
Mo Patel

Ok, ich sehe, dass meine Frage jetzt
Paul Matthews

2
Beachten Sie, dass Sie dies in einigen Szenarien möglicherweise nicht tun müssen, da die Datenzeile selbst die Transaktionsbearbeitung mit BeginEdit / EndEdit / CancelEdit unterstützt. Sie können auch .RejectChanges darauf aufrufen.
PeterG

Antworten:


185

Sie können die ImportRowMethode verwenden, um die Zeile mit demselben Schema von DataTable nach DataTable zu kopieren:

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

Aktualisieren:

Mit Ihrer neuen Bearbeitung glaube ich:

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

wird funktionieren


Anscheinend liefert Clone () nur eine flache Kopie. Denken Sie, dass dies ausreicht, um eine identische Kopie zu erstellen, oder ist ein tiefer Klon erforderlich?
Paul Matthews

5
@ PaulMatthews: Glücklicherweise enthält DataTable Werttypen, nicht Ref-Typ, so dass eine flache Kopie im
Wertetyp

16
Für Leute, die diesen Beitrag finden, füge ich Folgendes hinzu, da ich oft gefragt wurde, damit andere Leute möglicherweise verwirrt sind. Klon kopiere nur die Struktur, kopiere kopiere die Struktur dann die Daten. Das heißt, eine andere einfache Möglichkeit, Daten zu kopieren, sobald beide Tabellen instanziiert sind, besteht darin, eine neue Zeile in der Zieltabelle zu erstellen und Folgendes zu verwenden: destRow.ItemArray = sourceRow.ItemArrayFügen Sie dann einfach die Zeile mit hinzudestTable.Rows.Add(destRow);
Franck

1
Ich versuche, diese Methode zu verwenden, um einen Klon einer Datenreihe zu erhalten. Ich mache die folgenden Schritte, dann lösche ich die Datentabelle, die die Quellzeile enthält, und jetzt habe ich eine Quellzeile mit leeren Feldern.
Sergéу Isupov

Ich habe festgestellt, dass die Verwendung der ImportRow-Methode für mich funktioniert, die NewRow-Methode jedoch nicht.
OldDog

2

Hinweis: Die Antwort von cuongle enthält alle Zutaten, aber die Lösung kann optimiert werden (keine Notwendigkeit .ItemArray) und kann neu formuliert werden, um der gestellten Frage besser zu entsprechen.

Um einen (isolierten) Klon einer bestimmten System.Data.DataRowInstanz zu erstellen , haben Sie folgende Möglichkeiten:

// 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];

Hinweis: Shallow Klonen durchgeführt wird , die arbeitet , wie sie ist mit Spaltenwerte, die Werttyp - Instanzen, aber mehr Arbeit würde auch unabhängige Kopien von Spaltenwerten zu erstellen benötigt werden , um Referenztyp - Instanzen (und die Schaffung einer solchen unabhängige Kopien ist nicht immer möglich ).


1

Anscheinend möchten Sie nicht die gesamte DataTable als Kopie behalten, da Sie nur einige Zeilen benötigen, oder? Wenn Sie eine Kreteria haben, die Sie mit einer Auswahl in der Tabelle angeben können, können Sie nur diese Zeilen in ein zusätzliches Sicherungsarray von DataRow wie kopieren

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

Die .Select () -Funktion hat mehrere Optionen und diese kann zB als SQL gelesen werden

SELECT * FROM sourceTable WHERE searchColumn = value;

Anschließend können Sie die gewünschten Zeilen wie oben beschrieben importieren.

targetTable.ImportRows(rows[n])

... für jedes gültige n, das Sie mögen, aber die Spalten müssen in jeder Tabelle gleich sein.

Einige Dinge, die Sie über ImportRow wissen sollten, sind, dass es zur Laufzeit Fehler bei der Verwendung von Primärschlüsseln gibt!

Zuerst wollte ich überprüfen, ob bereits eine Zeile vorhanden war, die ebenfalls aufgrund eines fehlenden Primärschlüssels fehlschlug, aber dann schlug die Überprüfung immer fehl. Am Ende habe ich beschlossen, die vorhandenen Zeilen vollständig zu löschen und die gewünschten Zeilen erneut zu importieren.

Das zweite Problem hat geholfen zu verstehen, was passiert. Ich verwende die Importfunktion, um Zeilen mit einem ausgetauschten Eintrag in einer Spalte zu duplizieren. Mir wurde klar, dass es sich immer geändert hat und immer noch ein Verweis auf die Zeile im Array ist. Ich musste zuerst das Original importieren und dann den gewünschten Eintrag ändern.

In der Referenz werden auch die Primärschlüsselfehler erläutert, die beim ersten Versuch, die Zeile zu importieren, aufgetreten sind, da sie tatsächlich verdoppelt wurde.


-4

Um sicherzustellen, dass auf Ihre neue Zeile in der neuen Tabelle zugegriffen werden kann, müssen Sie die Tabelle schließen:

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

3
Was ist der Punkt der ersten Codezeile, wenn die zweite Codezeile die Variable neu zuweist?
Erik Philips

Diese Antwort könnte mehr Erklärung gebrauchen (und ich weiß nicht, was das Schließen der Tabelle bedeutet) und @ErikPhilips hat einen Punkt ( DataTable destination = source.Clone()sollte tun), aber ansonsten ist diese Antwort vollkommen in Ordnung und sogar dem .ItemArrayAnsatz in der akzeptierten Antwort vorzuziehen .
mklement0
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.