Simple way to copy or clone a DataRow?

C#DatatableDatarow

C# Problem Overview


I'm looking for a simple way to make a clone of a DataRow. Kind of like taking a snapshot of that Row and saving it. The values of original Row are then free to change but we still have another saved copy which doesn't change. Is this the correct way to do it?

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

Will this just set Snapshot's ItemArray reference to point to the one in Source or does it actually make a separate copy? Should I do this instead?

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

EDIT: I don't think the second code snippet actually compiles.

C# Solutions


Solution 1 - C#

You can use ImportRow method to copy Row from DataTable to DataTable with the same schema:

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

Update:

With your new Edit, I believe:

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

will work

Solution 2 - C#

Note: cuongle's helfpul answer has all the ingredients, but the solution can be streamlined (no need for .ItemArray) and can be reframed to better match the question as asked.

To create an (isolated) clone of a given System.Data.DataRow instance, you can do the following:

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

Note: Shallow cloning is performed, which works as-is with column values that are value type instances, but more work would be needed to also create independent copies of column values containing reference type instances (and creating such independent copies isn't always possible).

Solution 3 - C#

It seems you don't want to keep the whole DataTable as a copy, because you only need some rows, right? If you got a creteria you can specify with a select on the table, you could copy just those rows to an extra backup array of DataRow like

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

The .Select() function got several options and this one e.g. can be read as a SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Then you can import the rows you want as described above.

targetTable.ImportRows(rows[n])

...for any valid n you like, but the columns need to be the same in each table.

Some things you should know about ImportRow is that there will be errors during runtime when using primary keys!

First I wanted to check whether a row already existed which also failed due to a missing primary key, but then the check always failed. In the end I decided to clear the existing rows completely and import the rows I wanted again.

The second issue did help to understand what happens. The way I'm using the import function is to duplicate rows with an exchanged entry in one column. I realized that it always changed and it still was a reference to the row in the array. I first had to import the original and then change the entry I wanted.

The reference also explains the primary key errors that appeared when I first tried to import the row as it really was doubled up.

Solution 4 - C#

You can create an Extension for the class "DataTable" to create clones and add them to the table easy:

Example usage

DataTable dataTable; // given and contains rows

DataRow row = dataTable.Rows[0]; // Choose one row

// Only create the clone
DataRow clonedRow = dataTable.Clone(row);

// Create the clone and add it to the table
DataRow clonedRowAdded = dataTable.CloneAndAdd(row);

Extension handling this as follows

namespace CustomExtensions
{
    public static class DataTableExtensions
    {
        /// <summary>
        /// Operation: Clone sourceRow and add to destinationDataTable
        /// </summary>
        static public DataRow CloneAndAdd(this DataTable destinationDataTable,
            DataRow sourceRow)
        {
            DataRow clonedRow = destinationDataTable.Clone(sourceRow);
            destinationDataTable.Rows.Add(clonedRow);
            return clonedRow;
        }

        /// <summary>
        /// Operation: Clone sourceRow by destinationDataTable
        /// </summary>
        static public DataRow Clone(this DataTable destinationDataTable, 
            DataRow sourceRow)
        {
            DataRow clonedRow = destinationDataTable.NewRow();
            clonedRow.ItemArray = (object[])sourceRow.ItemArray.Clone();

            return clonedRow;
        }
    }
}

Solution 5 - C#

But to make sure that your new row is accessible in the new table, you need to close the table:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPaul MatthewsView Question on Stackoverflow
Solution 1 - C#cuongleView Answer on Stackoverflow
Solution 2 - C#mklement0View Answer on Stackoverflow
Solution 3 - C#BolleView Answer on Stackoverflow
Solution 4 - C#Ralf PeineView Answer on Stackoverflow
Solution 5 - C#rdjabarovView Answer on Stackoverflow