DataTable.Clone Method
Namespace: System.Data
Assembly: System.Data (in System.Data.dll)
If these classes have been derived, the clone will also be of the same derived classes.
Clone creates a new DataTable with the same structure as the original DataTable, but does not copy any data (the new DataTable will not contain any DataRows). To copy both the structure and data into a new DataTable, use Copy.
The following sample demonstrates how to update the structure and constraints of the destination table after you execute DataTable.Clone. The ClonedDataTable class will return a destination table and includes all the updating events. After the clone, structure changes in the source table won’t be reflected in the destination table. Specifically, this sample will:
Update the changes of the columns in source table.
Update the changes of the UniqueConstraint in source table.
Update the changes of the ForeignKeyConstraint in source table.
C# and Visual Basic projects with this code sample can be found on Developer Code Samples.
using System;
using System.Linq;
using System.Data;
using System.ComponentModel;
class Program {
static void Main(string[] args) {
DataTable courses = NewCourseDataTable();
Console.WriteLine("This is the source table:");
WriteDataTable(courses);
ClonedDataTable clonedResult = new ClonedDataTable(courses);
DataTable clonedCourses = clonedResult.DestinationTable;
Console.WriteLine("This is the destination table:");
WriteDataTable(clonedCourses);
// Add the events of updating column collection into the source table.
clonedResult.UpdateAddedColumn();
clonedResult.UpdateDeletedColumn();
// Add a DataColumn in source table.
DataColumn columnCreidts = new DataColumn("Credits", typeof(Int32));
courses.Columns.Add(columnCreidts);
Console.WriteLine("After add a column in source table, it's the result in the destination:");
WriteDataTable(clonedCourses);
// Add the event of updating UniqueConstraint into the source table.
clonedResult.UpdateUniqueConstraint();
// Add the unique constraint in source table.
UniqueConstraint uniqueConstraint = new UniqueConstraint(courses.Columns["CourseId"]);
courses.Constraints.Add(uniqueConstraint);
Console.WriteLine(@"If we add the unique constraint in source table and then insert the duplicate
rows into the destination table, we will get the following error:");
InsertDuplicateData(clonedCourses);
Console.WriteLine();
// Add the event of updating ForeignKeyConstraint into the source table.
clonedResult.UpdateForeignKeyConstraint();
// Add the ForeignKeyConstraint into the source table.
DataTable deparments = NewDeparmentDataTable();
DataSet dataset = new DataSet();
dataset.Tables.Add(courses);
dataset.Tables.Add(clonedCourses);
dataset.Tables.Add(deparments);
ForeignKeyConstraint foreignKey = new ForeignKeyConstraint(deparments.Columns["DepartmentId"], courses.Columns["DepartmentId"]);
courses.Constraints.Add(foreignKey);
Console.WriteLine(@"If we add the foreign key constraint in source table and then insert a row
without the parent into the destination table, we will get the following error:");
InsertNoParentRow(clonedCourses);
Console.WriteLine();
Console.WriteLine("Please press any key to exit...");
Console.ReadKey();
}
static private DataTable NewCourseDataTable() {
DataTable newTable = new DataTable();
DataColumn[] columns ={
new DataColumn("CourseId", typeof(String)),
new DataColumn("CourseName",typeof(String)),
new DataColumn("DepartmentId", typeof(Int32))
};
newTable.Columns.AddRange(columns);
newTable.Rows.Add("C1045", "Calculus", 7);
newTable.Rows.Add("C1061", "Physics", 1);
newTable.Rows.Add("C2021", "Composition", 2);
newTable.Rows.Add("C2042", "Literature", 2);
return newTable;
}
static private DataTable NewDeparmentDataTable() {
DataTable newTable = new DataTable();
DataColumn[] columns ={
new DataColumn("DepartmentId", typeof(Int32)),
new DataColumn("Name",typeof(String)),
};
newTable.Columns.AddRange(columns);
newTable.Rows.Add(1, "Engineering");
newTable.Rows.Add(2, "English");
newTable.Rows.Add(4, "Economics");
newTable.Rows.Add(7, "Mathematics");
return newTable;
}
static private void WriteDataTable(DataTable table) {
if (table == null)
return;
foreach (DataColumn column in table.Columns) {
Console.Write("{0,-15}", column.ColumnName);
}
Console.WriteLine();
foreach (DataRow row in table.Rows) {
for (int i = 0; i < table.Columns.Count; i++)
Console.Write("{0,-15}", row[i].ToString());
Console.WriteLine();
}
Console.WriteLine();
}
static private void InsertDuplicateData(DataTable table) {
try {
table.Rows.Add("C1045", "Calculus", 7);
table.Rows.Add("C1045", "Calculus", 7);
} catch (Exception e) {
Console.WriteLine("\"" + e.Message + "\"");
}
}
private static void InsertNoParentRow(DataTable table) {
try {
table.Rows.Add("C1061", "Physics", 11);
} catch (Exception e) {
Console.WriteLine("\"" + e.Message + "\"");
}
}
}
public class ClonedDataTable {
private DataTable sourceTable;
private DataTable destinationTable;
public ClonedDataTable(DataTable source) {
sourceTable = source;
// set the cloned result
destinationTable = sourceTable.Clone();
}
public void UpdateAddedColumn() {
sourceTable.Columns.CollectionChanged += new CollectionChangeEventHandler(ColumnAdded);
}
public void UpdateDeletedColumn() {
sourceTable.Columns.CollectionChanged += new CollectionChangeEventHandler(ColumnDeleted);
}
public void UpdateUniqueConstraint() {
sourceTable.Constraints.CollectionChanged += new CollectionChangeEventHandler(UniqueConstraint_Changed);
}
public void UpdateForeignKeyConstraint() {
sourceTable.Constraints.CollectionChanged += new CollectionChangeEventHandler(ForeignKeyConstraint_Changed);
}
// After the source table adds a column, the method will add the same column in the destination table.
void ColumnAdded(object sender, System.ComponentModel.CollectionChangeEventArgs e) {
if (e.Action == CollectionChangeAction.Add) {
DataColumn column = e.Element as DataColumn;
if (column != null) {
DataColumn newColumn = new DataColumn(column.ColumnName, column.DataType, column.Expression, column.ColumnMapping);
if (!destinationTable.Columns.Contains(newColumn.ColumnName))
destinationTable.Columns.Add(newColumn);
}
}
}
// After the source table deletes a column, the method will delete the same column in the destination table.
void ColumnDeleted(object sender, CollectionChangeEventArgs e) {
if (e.Action == CollectionChangeAction.Remove) {
DataColumn column = e.Element as DataColumn;
if (column != null)
if (destinationTable.Columns.Contains(column.ColumnName))
destinationTable.Columns.Remove(column.ColumnName);
}
}
// After the source table changes the UniqueConstraint, this method changes the same UniqueConstraint in destination table.
void UniqueConstraint_Changed(object sender, CollectionChangeEventArgs e) {
UniqueConstraint constraint = e.Element as UniqueConstraint;
if (constraint == null)
return;
String constraintName = constraint.ConstraintName;
if (e.Action == CollectionChangeAction.Add) {
DataColumn[] columns = new DataColumn[constraint.Columns.Count()];
Boolean isPrimaryKey = constraint.IsPrimaryKey;
// Get the columns used in new constraint from the destiantion table.
for (Int32 i = 0; i < constraint.Columns.Count(); i++) {
String columnName = constraint.Columns[i].ColumnName;
if (destinationTable.Columns.Contains(columnName))
columns[i] = destinationTable.Columns[columnName];
else
return;
}
UniqueConstraint newConstraint = new UniqueConstraint(constraintName, columns, isPrimaryKey);
if (!destinationTable.Constraints.Contains(constraintName))
destinationTable.Constraints.Add(newConstraint);
} else if (e.Action == CollectionChangeAction.Remove)
if (destinationTable.Constraints.Contains(constraintName))
destinationTable.Constraints.Remove(constraintName);
}
// After the source table changes the ForeignKeyConstraint, this method changes
// the same ForeignKeyConstraint in the destination table.
void ForeignKeyConstraint_Changed(object sender, CollectionChangeEventArgs e) {
ForeignKeyConstraint constraint = e.Element as ForeignKeyConstraint;
if (constraint == null)
return;
// If the source and destination are not in the same DataSet, don't change the ForeignKeyConstraint.
if (sourceTable.DataSet != destinationTable.DataSet)
return;
String constraintName = constraint.ConstraintName;
if (e.Action == CollectionChangeAction.Add) {
DataColumn[] columns = new DataColumn[constraint.Columns.Count()];
DataColumn[] parentColumns = constraint.RelatedColumns;
// Get the columns used in new constraint from the destination table.
for (int i = 0; i < constraint.Columns.Count(); i++) {
String columnName = constraint.Columns[i].ColumnName;
if (destinationTable.Columns.Contains(columnName))
columns[i] = destinationTable.Columns[columnName];
else
return;
}
ForeignKeyConstraint newConstraint = new ForeignKeyConstraint(constraintName, parentColumns, columns);
newConstraint.AcceptRejectRule = constraint.AcceptRejectRule;
newConstraint.DeleteRule = constraint.DeleteRule;
newConstraint.UpdateRule = constraint.UpdateRule;
if (!destinationTable.Constraints.Contains(constraintName))
destinationTable.Constraints.Add(newConstraint);
} else if (e.Action == CollectionChangeAction.Remove)
if (destinationTable.Constraints.Contains(constraintName))
destinationTable.Constraints.Remove(constraintName);
}
// return the destination table.
public DataTable DestinationTable {
get { return destinationTable; }
}
}
Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)
The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.