ADO - ADO.NET DataTable: ImportRow, Clone, and Copy Methods

In ADO.NET, the DataTable class is used to store data in memory in the form of rows and columns. When working with DataTable objects, developers often need to duplicate a table, create a new table with the same structure, or move rows from one table to another. ADO.NET provides three useful methods for these operations: ImportRow(), Clone(), and Copy(). Although these methods may appear similar, they perform different tasks and are useful in different situations.

1. ImportRow() Method

The ImportRow() method is used to copy an existing DataRow from one DataTable into another DataTable. The destination table must have a compatible structure with the source row.

The important point is that ImportRow() preserves the original DataRow state. This means information such as whether the row was originally added, modified, or deleted can be retained when the row is imported.

The basic syntax is:

destinationTable.ImportRow(sourceRow);

For example:

DataTable table1 = new DataTable();

table1.Columns.Add("ID", typeof(int));
table1.Columns.Add("Name", typeof(string));

table1.Rows.Add(1, "Rahul");
table1.Rows.Add(2, "Anita");

DataTable table2 = table1.Clone();

DataRow row = table1.Rows[0];

table2.ImportRow(row);

In this example, Clone() creates an empty table having the same structure as table1. The first row from table1 is then imported into table2 using ImportRow().

After the operation, table2 contains the row:

ID    Name
1     Rahul

ImportRow() is particularly useful when only selected rows need to be transferred rather than copying the entire table.

For example:

foreach (DataRow row in table1.Rows)
{
    if ((int)row["ID"] > 1)
    {
        table2.ImportRow(row);
    }
}

Here, only rows whose ID is greater than 1 are imported.

2. Clone() Method

The Clone() method creates a new DataTable containing the same structure as the original table but without copying its data.

The structure can include:

  • Column definitions

  • Data types

  • Primary key information

  • Constraints

  • Column properties

However, the rows themselves are not copied.

The syntax is:

DataTable newTable = originalTable.Clone();

Consider the following example:

DataTable employees = new DataTable("Employees");

employees.Columns.Add("EmployeeID", typeof(int));
employees.Columns.Add("EmployeeName", typeof(string));
employees.Columns.Add("Department", typeof(string));

employees.Rows.Add(101, "Arun", "IT");
employees.Rows.Add(102, "Meena", "HR");

DataTable employeeCopy = employees.Clone();

After executing Clone(), employeeCopy has the same columns as employees, but it contains zero rows.

Conceptually:

employees

EmployeeID    EmployeeName    Department
101           Arun            IT
102           Meena           HR


employeeCopy

EmployeeID    EmployeeName    Department

The table structure exists, but the records do not.

This makes Clone() useful when you need an empty table with the same schema as an existing table.

For example, you might retrieve a large dataset and then create an empty table to store only records that satisfy a particular condition.

DataTable filteredTable = employees.Clone();

foreach (DataRow row in employees.Rows)
{
    if (row["Department"].ToString() == "IT")
    {
        filteredTable.ImportRow(row);
    }
}

Here, Clone() creates the destination structure, while ImportRow() transfers the selected records.

3. Copy() Method

The Copy() method creates a completely new DataTable containing both the structure and the data of the original table.

The syntax is:

DataTable newTable = originalTable.Copy();

For example:

DataTable employees = new DataTable();

employees.Columns.Add("ID", typeof(int));
employees.Columns.Add("Name", typeof(string));

employees.Rows.Add(1, "Rahul");
employees.Rows.Add(2, "Anita");

DataTable employeeCopy = employees.Copy();

The resulting employeeCopy contains both the columns and the records:

ID    Name
1     Rahul
2     Anita

Unlike Clone(), Copy() does not create an empty table. It creates a new table containing the existing data as well.

This is useful when you need a separate DataTable containing the same dataset for additional processing.

Difference Between Clone() and Copy()

The easiest way to understand the difference is:

Clone()  = Structure only
Copy()   = Structure + Data

For example, suppose the original table contains 100 records.

After:

DataTable table2 = table1.Clone();

table2 contains:

Columns: Yes
Rows:    No

After:

DataTable table3 = table1.Copy();

table3 contains:

Columns: Yes
Rows:    100

Therefore, Clone() is appropriate when you need an empty table with an existing schema, while Copy() is appropriate when you need the schema and all the data.

Difference Between ImportRow() and Copy()

ImportRow() works at the row level, whereas Copy() works at the entire table level.

Suppose table1 contains 1,000 records but you only need 20 records in another table.

Using:

DataTable table2 = table1.Clone();

you can create an empty destination table and then import only the required records:

foreach (DataRow row in table1.Rows)
{
    if (/* condition */)
    {
        table2.ImportRow(row);
    }
}

Using:

DataTable table2 = table1.Copy();

would copy all 1,000 records, which may not be necessary.

Therefore, ImportRow() is better when selective row transfer is required.

Important Difference Between ImportRow() and Rows.Add()

A common source of confusion is the difference between ImportRow() and Rows.Add().

Consider:

destination.Rows.Add(sourceRow);

and:

destination.ImportRow(sourceRow);

These operations are not identical.

ImportRow() is specifically designed to import an existing DataRow while preserving its row state and related information where applicable.

Rows.Add() adds a row to the destination table as a new row. It is commonly used when creating a new row or adding values directly.

For example:

DataRow newRow = destination.NewRow();

newRow["ID"] = 10;
newRow["Name"] = "Kiran";

destination.Rows.Add(newRow);

Here, a new row is created and then added to the destination.

With ImportRow():

destination.ImportRow(sourceRow);

an existing row from another table is imported.

Practical Example

Consider an application that retrieves customer information from a database.

DataTable customers = GetCustomers();

Suppose the application needs a separate table containing only customers from Karnataka.

First, create a table with the same structure:

DataTable karnatakaCustomers = customers.Clone();

Then import the required rows:

foreach (DataRow row in customers.Rows)
{
    if (row["State"].ToString() == "Karnataka")
    {
        karnatakaCustomers.ImportRow(row);
    }
}

The original table remains unchanged, while the new table contains only the required records.

This approach is useful for filtering data, preparing reports, creating subsets of datasets, and transferring selected records between in-memory tables.

When Should You Use Each Method?

Use Clone() when you need a new empty DataTable with the same structure as an existing table.

Use Copy() when you need a complete duplicate containing both the structure and the data.

Use ImportRow() when you need to transfer specific existing rows from one DataTable to another while retaining the source row's state information.

A simple way to remember them is:

Clone()
    ↓
Copies structure
Does not copy rows

Copy()
    ↓
Copies structure
Copies all rows

ImportRow()
    ↓
Copies selected existing rows
Works between DataTables
Preserves DataRow state

Conclusion

ImportRow(), Clone(), and Copy() are useful DataTable operations for managing in-memory data in ADO.NET. Clone() is mainly concerned with duplicating the table schema, Copy() duplicates both schema and records, and ImportRow() allows individual existing rows to be transferred into another compatible table.

Understanding these differences is important when developing ADO.NET applications because choosing the wrong method can result in unnecessary data duplication or unexpected table contents. In applications where only a subset of records is required, combining Clone() with ImportRow() provides a clean and efficient approach for creating a new table containing selected records.