Простий спосіб копіювання або клонування DataRow?


118

Я шукаю простий спосіб зробити клон DataRow. Начебто як зробити знімок цього ряду і зберегти його. Значення оригінального рядка потім вільно змінюватися, але у нас все ще є збережена копія, яка не змінюється. Це правильний спосіб зробити це?

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

Чи просто встановить посилання ItemArray Snapshot так, щоб вона вказувала на джерело в Source, чи це насправді робить окрему копію? Чи слід це робити замість цього?

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

EDIT: Я не думаю, що другий фрагмент коду насправді складається.


Я не впевнений, що я розумію, ви хочете скопіювати datarow з однієї таблиці в іншу таблицю? Якщо так, я вважаю, що ви користуєтеся DataTable.ImportRow.
Пн Патель

Гаразд, я бачу, що моє питання потребує перепрацювання зараз
Пол Меттьюс

2
Зауважте, що в деяких сценаріях вам це не потрібно буде робити, оскільки сам datarow підтримує редагування транзакцій за допомогою BeginEdit / EndEdit / CancelEdit; також ви можете зателефонувати .RejectChanges на ньому.
peterG

Відповіді:


185

Ви можете використовувати ImportRowметод для копіювання рядка з DataTable у DataTable за тією ж схемою:

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

Оновлення:

З новою редакцією я вважаю:

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

буду працювати


Мабуть, Clone () надає лише дрібну копію. Як ви думаєте, цього буде достатньо для створення ідентичної копії або потрібен глибокий клон?
Пол Меттьюс

5
@PaulMatthews: На щастя DataTable містить типи значень, а не тип рефлексу, тому мілка копія у значенні типу os те саме з глибокою копією
cuongle

16
Для людей, які знаходять цю посаду, я додаю наступне, оскільки мене часто запитують, тому я здогадуюсь, що інших людей може заплутати. Клонувати копіювати лише структуру, Копіювати копіювати структуру, а потім дані. Про це говорять, ще одним простим способом копіювання даних, коли обидві таблиці ідентифіковані, є створення нового рядка в цільовій таблиці та використання наступного: destRow.ItemArray = sourceRow.ItemArrayпотім просто додати рядок назад зdestTable.Rows.Add(destRow);
Франк

1
Я намагаюся використовувати цей метод для отримання клону даних. Виконую наступні кроки, потім очищую таблицю даних, яка містить вихідний рядок, і тепер у мене є рядок джерела з порожніми полями.
Сергей Ісупов

Я виявив, що використання методу ImportRow працювало для мене, де метод NewRow цього не зробив.
OldDog

2

Примітка: відповідь helfpul cuongle містить усі інгредієнти, але рішення може бути спрощеним (не потрібно .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];

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


1

Здається, ви не хочете зберігати весь DataTable як копію, тому що вам потрібні лише кілька рядків, правда? Якщо у вас є кретерія, яку ви можете вказати виберіть у таблиці, ви можете скопіювати лише ці рядки в додатковий резервний масив DataRow, як

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

Функція .Select () отримала кілька варіантів, і цей варіант, наприклад, можна прочитати як SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Потім ви можете імпортувати потрібні рядки, як описано вище.

targetTable.ImportRows(rows[n])

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

Деякі речі, про які ви повинні знати про ImportRow, - це те, що під час використання первинних ключів будуть виникати помилки під час виконання!

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

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

Посилання також пояснює помилки первинного ключа, які з’явилися, коли я вперше спробував імпортувати рядок, оскільки він насправді був подвоєний.


-4

Але щоб переконатися, що ваш новий рядок доступний у новій таблиці, потрібно закрити таблицю:

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

3
Який сенс першого рядка коду, якщо другий рядок коду повторно призначить змінну?
Ерік Філіпс

Ця відповідь могла б використати більше пояснень (і я не знаю, що потрібно закрити таблицю ), а @ErikPhilips має крапку ( DataTable destination = source.Clone()слід робити), але в іншому випадку ця відповідь є цілком чудовою і навіть кращою для .ItemArrayпідходу у прийнятій відповіді.
mklement0
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.