Un moyen simple de copier ou de cloner un DataRow?

118

Je recherche un moyen simple de créer un clone d'un DataRow. Un peu comme prendre un instantané de cette ligne et l'enregistrer. Les valeurs de Row d'origine sont alors libres de changer mais nous avons encore une autre copie enregistrée qui ne change pas. Est-ce la bonne façon de procéder?

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

Cela va-t-il simplement définir la référence ItemArray de Snapshot pour pointer vers celui de Source ou fait-il réellement une copie séparée? Dois-je faire cela à la place?

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

EDIT: Je ne pense pas que le deuxième extrait de code se compile réellement.

Paul Matthews
la source
Je ne suis pas sûr de comprendre, vous souhaitez copier un flux de données d'une table vers une autre table? Si c'est le cas, je pense que l'utilisation de DataTable.ImportRow est ce que vous recherchez.
Mo Patel
Ok, je vois que ma question doit être retravaillée maintenant
Paul Matthews
2
Notez que dans certains scénarios, vous n'aurez peut-être pas besoin de le faire car le flux de données lui-même prend en charge l'édition transactionnelle avec BeginEdit / EndEdit / CancelEdit; vous pouvez également appeler .RejectChanges dessus.
peterG

Réponses:

185

Vous pouvez utiliser la ImportRowméthode pour copier Row de DataTable vers DataTable avec le même schéma:

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

Mettre à jour:

Avec votre nouvelle édition, je crois:

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

marchera

cuongle
la source
Apparemment, Clone () ne fournit qu'une copie superficielle. Pensez-vous que cela suffira pour créer une copie identique ou un clone profond est-il nécessaire?
Paul Matthews
5
@PaulMatthews: Heureusement, DataTable contient des types de valeur, pas de type ref, donc une copie superficielle dans le type de valeur est la même chose avec la copie profonde
cuongle
16
Pour les personnes qui trouvent ce message, j'ajouterai ce qui suit car on m'a souvent demandé, donc je suppose que d'autres personnes pourraient être confuses. Cloner copie uniquement la structure, Copier copier la structure puis les données. Cela dit, un autre moyen simple de copier des données une fois les deux tables instanciées consiste à créer une nouvelle ligne dans la table de destination et à utiliser ce qui suit: destRow.ItemArray = sourceRow.ItemArraypuis rajoutez simplement la ligne avecdestTable.Rows.Add(destRow);
Franck
1
J'essaye d'utiliser cette méthode pour obtenir un clone d'un datarow. Je fais les étapes suivantes, puis j'efface la table de données qui contient la ligne source et maintenant j'ai une ligne source avec des champs vides.
Sergеу Isupov
J'ai trouvé que l'utilisation de la méthode ImportRow fonctionnait pour moi, contrairement à la méthode NewRow.
OldDog
2

Remarque: la réponse helfpul de cuongle contient tous les ingrédients, mais la solution peut être simplifiée (pas besoin .ItemArray) et peut être recadrée pour mieux correspondre à la question posée.

Pour créer un clone (isolé) d'une System.Data.DataRowinstance donnée , vous pouvez effectuer les opérations suivantes:

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

Remarque: le clonage superficiel est effectué , qui fonctionne tel quel avec les valeurs de colonne qui sont des instances de type valeur , mais plus de travail serait nécessaire pour créer également des copies indépendantes des valeurs de colonne contenant des instances de type référence (et la création de telles copies indépendantes n'est pas toujours possible ).

mklement0
la source
1

Il semble que vous ne souhaitiez pas conserver l'intégralité de DataTable en tant que copie, car vous n'avez besoin que de quelques lignes, non? Si vous avez un critère que vous pouvez spécifier avec une sélection sur la table, vous pouvez copier uniquement ces lignes dans un tableau de sauvegarde supplémentaire de DataRow comme

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

La fonction .Select () a plusieurs options et celle-ci peut par exemple être lue comme un SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Ensuite, vous pouvez importer les lignes souhaitées comme décrit ci-dessus.

targetTable.ImportRows(rows[n])

... pour tout n valide que vous aimez, mais les colonnes doivent être les mêmes dans chaque table.

Certaines choses que vous devez savoir sur ImportRow sont qu'il y aura des erreurs lors de l'exécution lors de l'utilisation de clés primaires!

Tout d'abord, je voulais vérifier s'il existait déjà une ligne qui a également échoué en raison d'une clé primaire manquante, mais la vérification a toujours échoué. En fin de compte, j'ai décidé d'effacer complètement les lignes existantes et d'importer à nouveau les lignes que je voulais.

Le deuxième problème a aidé à comprendre ce qui se passe. La façon dont j'utilise la fonction d'importation est de dupliquer des lignes avec une entrée échangée dans une colonne. J'ai réalisé que cela changeait toujours et que c'était toujours une référence à la ligne dans le tableau. J'ai d'abord dû importer l'original, puis modifier l'entrée que je voulais.

La référence explique également les erreurs de clé primaire qui sont apparues lorsque j'ai essayé d'importer la ligne pour la première fois car elle était vraiment doublée.

Bolle
la source
-4

Mais pour vous assurer que votre nouvelle ligne est accessible dans la nouvelle table, vous devez fermer la table:

DataTable destination = new DataTable(source.TableName);
destination = source.Clone();
DataRow sourceRow = source.Rows[0];
destination.ImportRow(sourceRow);
rdjabarov
la source
3
Quel est le point de la première ligne de code si la deuxième ligne de code réassigne la variable?
Erik Philips
Cette réponse pourrait nécessiter plus d'explications (et je ne sais pas ce que signifie le besoin de fermer le tableau ) et @ErikPhilips a un point ( DataTable destination = source.Clone()devrait faire), mais sinon cette réponse est parfaitement correcte et même préférable à l' .ItemArrayapproche de la réponse acceptée.
mklement0