7.8 Cloning the Schema of the Table

7.8 Cloning the Schema of the Table

The Clone( ) method creates a new DataTable with the same schema as the original, but it contains none of the data in the original DataTable . The following example uses the Clone( ) method to create a new DataTable :

 // create a DataTable object variable to receive the clone
DataTable cloneDt;
cloneDt = dt.Clone(); 

7.9 Copying the Table

The Copy( ) method creates a new DataTable with the same structure and data as the original. The following example uses the Copy( ) method to create a new DataTable :

 // create a DataTable object variable to receive the copy
DataTable copyDt;
copyDt = dt.Copy(); 

7.10 Selecting a Subset of Rows

The Select( ) method returns a subset of rows from the DataTable and returns the result as a DataRow array. The four overloads take optional arguments specifying the filter criteria, sort order, and DataViewRowState of the rows to be returned. The following example illustrates this concept:

 // all rows with order amount > 100, sorted on the order date descending
DataRow[] dra = dt.Select("OrderAmount>100.00", "OrderDate DESC"); 

The following example returns all modified rows in the table:

 DataRow[] dra = dt.Select(null, null, DataViewRowState.ModifiedCurrent); 

7.11 Performing Aggregate Calculations

The Compute( ) method computes the result of an aggregate query on the rows in the table that meet the filter criteria. Here's an example that illustrates this:

 DataTable dt = new Table();
dt.Columns.Add("OrderId", typeof(System.Int32));
dt.Columns.Add("OrderAmount", typeof(System.Decimal));

// ... add some rows

// computes the sum of order amounts for all orders with Id less than 10
Decimal totalOrderAmount = dt.Compute("SUM(OrderAmount)", "OrderId<10") 

7.12 Removing All Data

The Clear( ) method removes all rows from the DataTable :

 dt.Clear(); 

7.13 Resetting the Table

The Reset( ) method returns the DataTable to its original state. This method can discard the existing DataTable and start working with a new DataTable rather than instantiating a new DataTable object.

 dt.Reset(); 

7.14 Identifying Errors in the Table

The GetErrors( ) method returns an array of the rows that contain errors, whether they are constraint violations or failed update attempts. The RowError property or the SetColumnError( ) method of the DataRow object can be used to set an error, or an error can be set by the DataAdapter in response to errors that occur while data is being reconciled with the data source. The HasErrors( ) method should be called prior to calling GetErrors( ) to determine whether the call to GetErrors( ) is necessary. The following example shows how to use these methods :

 DataRow[] errorRow;
if(dt.HasErrors())
{
    errorRows = dt.GetErrors();
    for(Int32 i = 0; i<errorRows.Length; i++)
    {
        // ... resolve the error for the row

        // clear the error for resubmitting
        errorRows[i].ClearErrors();
    }
} 

7.15 DataTable Events

The following section describes DataTable events.

7.15.1 ColumnChanged and ColumnChanging

The ColumnChanged and ColumnChanging events can be handled to validate data or control user interface elements. The ColumnChanging event is raised when a value is being changed in a specified column; the ColumnChanged event is raised after the value in the column has been changed. Both events pass a DataColumnChangeEventArgs argument to the event handler that provide information specific to the event.

The following code demonstrates handling the ColumnChanging and ColumnChanged events to perform data validation and logging:

 DataTable dt = new DataTable();

dt.ColumnChanged += new DataColumnChangeEventHandler(dt_ColumnChanged);
dt.ColumnChanging += new DataColumnChangeEventHandler(dt_ColumnChanging);

private static void dt_ColumnChanging(object sender,
    DataColumnChangeEventArgs e);
{
    if (e.Column.ColumnName == "MyColumn")
    {
        if(e.ProposedValue.Equals("Invalid Data")
        {
            e.Row.RowError = "Invalid data.";
            e.Row.SetColumnError(e.Column, "Column value " +
                "cannot be " e.ProposedValue.ToString());    
        }
    }
}

private static void ds_ColumnChanged(object sender,
    DataColumnChangeEventArgs e);
{
    System.IO.TextWriter tw = System.IO.File.AppendText("colchange.log");
    tw.WriteLine("ColumnChanging: Name = {0}; ProposedValue = {1}; " +
        "Row Id = {2}", e.ColumnName, e.ProposedValue.ToString(),
        e.Row["Id"].ToString());
    tw.Close(); 
} 

7.15.2 RowChanged, RowChanging, RowDeleted, and RowDeleting

The DataTable raises four events in response to actions performed on rows. These events are RowChanging and RowChanged, which are raised, respectively, before and after a row is edited; RowDeleting and RowDeleted are raised, respectively, before and after a row is marked for deletion. These events can support custom validation logic similar to the ColumnChanging and ColumnChanged events described earlier. All four events pass a DataRowChangeEventArgs argument to the event handler providing information specific to the event.

The following code demonstrates handling the RowChanged , RowChanging , RowDeleted , and RowDeleting events:

 DataTable dt = new DataTable();

dt.RowChanged+= new DataRowChangeEventHandler(dt_RowChanged);
dt.RowChanging+= new DataRowChangeEventHandler(dt_RowChanging);
dt.RowDeleted+= new DataRowChangeEventHandler(dt_RowDeleted);
dt.RowDeleting+= new DataRowChangeEventHandler(dt_RowDeleting);

private void dt_RowChanged(object sender, DataRowChangeEventArgs e);
{
    MessageBox.Show("RowChanged: Action  =  " + e.Action + "; " +
        "Row Id  =  " + e.Row["Id"].ToString());
}

private void dt_RowChanging(object sender, DataRowChangeEventArgs e);
{
    MessageBox.Show("RowChanging: Action  =  " + e.Action + "; " +
        "Row Id  =  " + e.Row["Id"].ToString());
}

private void dt_RowDeleted(object sender, DataRowChangeEventArgs e);
{
    MessageBox.Show("RowDeleted: Action  =  " + e.Action + "; " +
        "Row Id  =  " + e.Row["Id"].ToString());
}

private void dt_RowDeleting(object sender, DataRowChangeEventArgs e);
{
    MessageBox.Show("RowDeleting: Action  =  " + e.Action + "; " +
        "Row Id  =  " + e.Row["Id"].ToString());
}