Простой способ скопировать или клонировать DataRow?

Я ищу простой способ сделать клон DataRow. Это как сделать снимок этой строки и сохранить его. Значения исходной строки могут быть изменены, но у нас все еще есть другая сохраненная копия, которая не изменяется. Это правильный способ сделать это?

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

Будет ли это просто устанавливать ссылку на ItemArray моментального снимка так, чтобы она указывала на ссылку в Source, или она действительно создает отдельную копию? Должен ли я сделать это вместо этого?

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

РЕДАКТИРОВАТЬ: я не думаю, что второй фрагмент кода действительно компилируется.


person Paul Matthews    schedule 19.08.2012    source источник
comment
Я не уверен, что понимаю, вы хотите скопировать строку данных из одной таблицы в другую? Если это так, я считаю, что использование DataTable.ImportRow - это то, что вам нужно.   -  person Mo Patel    schedule 19.08.2012
comment
Хорошо, я вижу, что мой вопрос нужно переработать сейчас   -  person Paul Matthews    schedule 19.08.2012
comment
Обратите внимание, что в некоторых сценариях вам может не потребоваться это делать, потому что поток данных сам поддерживает редактирование транзакций с помощью BeginEdit / EndEdit / CancelEdit; также вы можете вызвать для него .RejectChanges.   -  person peterG    schedule 25.03.2014


Ответы (4)


Для скопируйте строку из DataTable в DataTable с той же схемой:

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

Обновление:

С вашим новым Edit, я считаю:

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

буду работать

person cuongle    schedule 19.08.2012
comment
По-видимому, Clone () предоставляет только неглубокую копию. Как вы думаете, этого будет достаточно для создания идентичной копии или требуется глубокий клон? - person Paul Matthews; 19.08.2012
comment
@PaulMatthews: К счастью, DataTable содержит типы значений, а не тип ссылки, поэтому неглубокая копия в типе значения аналогична глубокой копии - person cuongle; 19.08.2012
comment
Для людей, нашедших этот пост, я добавлю следующее, так как меня часто спрашивали, поэтому я думаю, что другие люди могут быть сбиты с толку. Клонировать - копировать только структуру, Копировать - копировать структуру, а затем данные. При этом говорится, что еще один простой способ скопировать данные после создания экземпляров обеих таблиц - создать новую строку в целевой таблице и использовать следующее: destRow.ItemArray = sourceRow.ItemArray затем просто добавьте строку обратно с помощью destTable.Rows.Add(destRow); - person Franck; 18.03.2014
comment
Пытаюсь использовать этот метод для получения клона datarow. Я делаю следующие шаги, затем очищаю таблицу данных, содержащую исходную строку, и теперь у меня есть исходная строка с пустыми полями. - person Sergеу Isupov; 09.10.2015
comment
Я обнаружил, что у меня работает метод ImportRow, тогда как метод NewRow - нет. - person OldDog; 25.02.2017
comment
@cuongle: Похоже, нет ограничений на хранение ссылочных типов в таблицах данных, по крайней мере, в настоящее время. Было ли это по-другому в более ранних версиях .NET? - person mklement0; 11.11.2019

Примечание. Ответ cuongle helfpul содержит все ингредиенты, но решение можно оптимизировать (.ItemArray не требуется) и можно изменить, чтобы лучше соответствовать заданному вопросу.

Чтобы создать (изолированный) клон заданного System.Data.DataRow экземпляра, вы можете сделать следующее:

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

Примечание. Выполняется поверхностное клонирование, которое работает как есть со значениями столбцов, которые являются экземплярами типа значения, но также потребуется дополнительная работа, чтобы создавать независимые копии значений столбцов, содержащих экземпляры ссылочного типа (и создание таких независимых копий не всегда возможно).

person mklement0    schedule 11.11.2019

Похоже, вы не хотите хранить весь DataTable как копию, потому что вам нужны только несколько строк, верно? Если у вас есть критерия, которую вы можете указать с помощью выбора в таблице, вы можете скопировать только эти строки в дополнительный резервный массив DataRow, например

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

У функции .Select () есть несколько опций, и этот, например, можно читать как SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Затем вы можете импортировать нужные строки, как описано выше.

targetTable.ImportRows(rows[n])

... для любого допустимого n, которое вам нравится, но столбцы должны быть одинаковыми в каждой таблице.

Некоторые вещи, которые вы должны знать об ImportRow, заключаются в том, что во время выполнения при использовании первичных ключей будут возникать ошибки!

Сначала я хотел проверить, существует ли уже строка, что также не удалось из-за отсутствия первичного ключа, но тогда проверка всегда терпела неудачу. В конце концов я решил полностью очистить существующие строки и снова импортировать нужные строки.

Вторая проблема действительно помогла понять, что происходит. Я использую функцию импорта для дублирования строк с замененной записью в одном столбце. Я понял, что он всегда менялся и по-прежнему оставался ссылкой на строку в массиве. Сначала мне пришлось импортировать оригинал, а затем изменить запись, которую я хотел.

В справочнике также объясняются ошибки первичного ключа, которые возникли, когда я впервые попытался импортировать строку, поскольку она действительно была увеличена вдвое.

person Bolle    schedule 24.02.2020

Но чтобы убедиться, что ваша новая строка доступна в новой таблице, вам нужно закрыть таблицу:

DataTable destination = new DataTable(source.TableName);
destination = source.Clone();
DataRow sourceRow = source.Rows[0];
destination.ImportRow(sourceRow);
person rdjabarov    schedule 04.04.2015
comment
В чем смысл первой строки кода, если вторая строка кода переназначает переменную? - person Erik Philips; 11.10.2018
comment
В этом ответе можно было бы использовать дополнительные объяснения (и я не знаю, что означает need to close the table), и у @ErikPhilips есть точка (DataTable destination = source.Clone() должен делать), но в остальном этот ответ совершенно прекрасен и даже предпочтительнее к подходу .ItemArray в принятом ответе. - person mklement0; 12.11.2019