Copying Tables from One DataSet to Another
Problem
You need to copy an existing schema and data from one DataSet to another.
Solution
Use one of the following techniques:
- Use the Copy( ) method of the DataTable when all of the data for a table needs to be copied .
- Use the Clone( ) method of the DataTable to create the schema for each table in the destination DataSet when only a subset of the data needs to be copied. You can use the ImportRows( ) method of the DataTable to copy the subset of rows from the source to the destination table.
Once the destination tables are created and the data is copied into them, the example shows how to create the DataRelation objects from the source DataSet in the destination DataSet .
The sample code contains two event handlers:
Form.Load
Sets up the sample by creating a DataSet containing the Orders and Order Details tables from Northwind and a relation between the two tables. The default view for the Orders table is bound to a data grid on the form.
Copy Button.Click
Creates a destination DataSet and copies the schema and specified data into it from the source DataSet created in the Form.Load event handler.
The C# code is shown in Example 5-2.
Example 5-2. File: CopyTablesBetweenDataSetsForm.cs
// Namespaces, variables, and constants using System; using System.Configuration; using System.Windows.Forms; using System.Data; using System.Data.SqlClient; // Table name constants private const String ORDERS_TABLE = "Orders"; private const String ORDERDETAILS_TABLE = "OrderDetails"; // Relation name constants private const String ORDERS_ORDERDETAILS_RELATION = "Orders_OrderDetails_Relation"; // Field name constants private const String ORDERID_FIELD = "OrderID"; private const String ORDERDATE_FIELD = "OrderDate"; private const String EMPLOYEEID_FIELD = "EmployeeID"; private DataSet dsSource; // . . . private void CopyTablesBetweenDataSetsForm_Load(object sender, System.EventArgs e) { dsSource = new DataSet("Source"); SqlDataAdapter da; // Fill the Order table and add it to the DataSet. da = new SqlDataAdapter("SELECT * FROM Orders", ConfigurationSettings.AppSettings["Sql_ConnectString"]); DataTable orderTable = new DataTable(ORDERS_TABLE); da.FillSchema(orderTable, SchemaType.Source); da.Fill(orderTable); dsSource.Tables.Add(orderTable); // Fill the OrderDetails table and add it to the DataSet. da = new SqlDataAdapter("SELECT * FROM [Order Details]", ConfigurationSettings.AppSettings["Sql_ConnectString"]); DataTable orderDetailTable = new DataTable(ORDERDETAILS_TABLE); da.FillSchema(orderDetailTable, SchemaType.Source); da.Fill(orderDetailTable); dsSource.Tables.Add(orderDetailTable); // Create a relation between the tables. dsSource.Relations.Add(ORDERS_ORDERDETAILS_RELATION, dsSource.Tables[ORDERS_TABLE].Columns[ORDERID_FIELD], dsSource.Tables[ORDERDETAILS_TABLE].Columns[ORDERID_FIELD], true); // Bind the source and destination DataSet to the grids. sourceDataGrid.DataSource = dsSource.Tables[ORDERS_TABLE].DefaultView; } private void copyButton_Click(object sender, System.EventArgs e) { // Create the destination DataSet into which to copy tables DataSet dsDest = new DataSet("Destination"); if (copyAllRadioButton.Checked) { foreach(DataTable sourceTable in dsSource.Tables) { // First technique: when all rows need to be copied dsDest.Tables.Add(sourceTable.Copy( )); } } else if (copySubsetRadioButton.Checked) { int employeeId = 0; try { employeeId = Convert.ToInt32(employeeIdTextBox.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); return; } // Second technique: can be used to import subset foreach(DataTable dtSource in dsSource.Tables) { // Add logic to selectively copy tables. dsDest.Tables.Add(dtSource.Clone( )); } // Copy rows for selected employee from the Orders table. foreach(DataRow parentRow in dsSource.Tables[ORDERS_TABLE].Select( EMPLOYEEID_FIELD + "=" + employeeId)) { dsDest.Tables[ORDERS_TABLE].ImportRow(parentRow); // Copy the Order Details for the Order. foreach(DataRow childRow in parentRow.GetChildRows( ORDERS_ORDERDETAILS_RELATION)) { dsDest.Tables[ ORDERDETAILS_TABLE].ImportRow(childRow); } } } // Create the relations in the destination DataSet. // Iterate over the collection of relations in the source. foreach(DataRelation sourceRelation in dsSource.Relations) { // Get the name of the parent and child table for the relation. String parentTableName = sourceRelation.ParentTable.TableName; String childTableName = sourceRelation.ChildTable.TableName; // Get the number of parent columns for the source relation. int nCol = sourceRelation.ParentColumns.Length; // Create an array of parent columns in the destination. DataColumn[] parentCols = new DataColumn[nCol]; for(int i = 0; i < nCol; i++) parentCols[i] = dsDest.Tables[parentTableName].Columns[ sourceRelation.ParentColumns[i].Ordinal]; // Create an array of child columns in the destination. DataColumn[] childCols = new DataColumn[nCol]; for(int i = 0; i < nCol; i++) childCols[i] = dsDest.Tables[childTableName].Columns[ sourceRelation.ChildColumns[i].Ordinal]; // Create the relation in the destination DataSet. dsDest.Relations.Add( new DataRelation(sourceRelation.RelationName, parentCols, childCols, false)); } // Set the enforce constraints flag to match the source DataSet. dsDest.EnforceConstraints = dsSource.EnforceConstraints; // Bind the default view of the Orders table to the grid. destDataGrid.DataSource = dsDest.Tables[ORDERS_TABLE].DefaultView; }
Discussion
This sample demonstrates two scenarios for copying tables from one DataSet to another.
In the first scenario, all of the data and tables in the source DataSet are copied to the destination. This is accomplished by iterating over the collection of tables in the source DataSet and using the Copy( ) method of each DataTable object to copy both the schema and data for each table into the destination DataSet .
In the second scenario, only a subset of the data in the source DataSet is copied to the destination. Since there is a relation in place between the Orders and Order Details tables in this case, only the child records related to the selected parent records are copied to the destination.
Once the data has been copied, the DataRelation objects are copied by iterating over the collection of DataRelation objects in the source DataSet , and adding them to the destination DataSet . This involves creating an array of parent and source columns for the destination DataRelation from the parent and child column ordinals in the source DataRelation . This information, together with the name of the source DataRelation is used to create the DataRelation in the destination DataSet . Finally, the EnforceConstraints property in the destination DataRelation is set to match the source.