DataRelations

A DataRelation object represents a relationship between two DataTable objects within a DataSet. These relationships are fundamental to modeling hierarchical data and enabling navigation between related tables. They are analogous to foreign key constraints in relational databases.

DataRelation objects allow you to:

Creating a DataRelation

You can create a DataRelation by using the DataRelation constructor or by adding a relation to a DataSet's Relations collection. The most common approach is to add it to the DataSet.

Using the DataSet.Relations.Add Method

The DataSet.Relations.Add method offers several overloads. A common overload requires the name of the relation, an array of parent key columns, and an array of child key columns.

Example: Creating a Parent-Child Relation


// Assume ds is a DataSet containing two DataTables: 'Customers' and 'Orders'
// Each table has a primary key column named 'CustomerID'.

// Define the columns that link the tables
DataColumn[] parentColumns = new DataColumn[] { ds.Tables["Customers"].Columns["CustomerID"] };
DataColumn[] childColumns = new DataColumn[] { ds.Tables["Orders"].Columns["CustomerID"] };

// Create the DataRelation
DataRelation relation = new DataRelation("CustomerOrders", parentColumns, childColumns);

// Add the relation to the DataSet
ds.Relations.Add(relation);
            

You can also specify a name for the relation, a parent DataColumn, and a child DataColumn if the keys are single columns:

Example: Simplified Single-Column Relation


// Assume ds is a DataSet containing 'Customers' and 'Orders' DataTables
// with a single 'CustomerID' column in each.

ds.Relations.Add("CustomerOrders", ds.Tables["Customers"].Columns["CustomerID"], ds.Tables["Orders"].Columns["CustomerID"]);
            

Navigating DataRelations

Once a DataRelation is established, you can traverse the relationships between rows.

Navigating from Parent to Child Rows

Use the GetChildRows method of a DataRow object to retrieve the related child rows.

Example: Getting Child Orders for a Customer


// Assume 'customerRow' is a DataRow from the 'Customers' table
// and the 'CustomerOrders' relation has been added.

DataRow[] childOrders = customerRow.GetChildRows("CustomerOrders");

foreach (DataRow orderRow in childOrders)
{
    Console.WriteLine($"Order ID: {orderRow["OrderID"]}, Date: {orderRow["OrderDate"]}");
}
            

Navigating from Child to Parent Row

Use the GetParentRow method of a DataRow object to retrieve the related parent row.

Example: Getting Parent Customer for an Order


// Assume 'orderRow' is a DataRow from the 'Orders' table
// and the 'CustomerOrders' relation has been added.

DataRow parentCustomer = orderRow.GetParentRow("CustomerOrders");

if (parentCustomer != null)
{
    Console.WriteLine($"Customer Name: {parentCustomer["CompanyName"]}");
}
            

Enforcing Referential Integrity

DataRelation objects can optionally enforce referential integrity, similar to foreign key constraints in databases. This prevents the creation of "orphan" records (child rows without a corresponding parent row).

Creating Relations with Constraints

When creating a DataRelation, you can specify a ForeignKeyConstraint to enforce referential integrity. This is often done implicitly when adding a relation with keys to a DataSet, as the DataSet automatically creates constraints.

You can set properties on the ForeignKeyConstraint (which is associated with the DataRelation) to control the behavior on update or delete operations:

Note: By default, when a DataRelation is added to a DataSet, it also creates a corresponding ForeignKeyConstraint that enforces referential integrity.

Filtering Child Rows with DataView

DataRelation objects are often used in conjunction with DataView objects to filter child rows based on the current row in the parent table.

Example: Filtering Orders for a Selected Customer in a Grid


// Assume a GridView displays customers. When a customer is selected:

// Get the selected customer row
DataRowView selectedCustomerView = (DataRowView)customerGridView.SelectedRow.DataItem;
DataRow selectedCustomerRow = selectedCustomerView.Row;

// Get the relation name
string relationName = "CustomerOrders";

// Filter the DataView for orders related to the selected customer
DataView ordersView = new DataView(ds.Tables["Orders"]);
ordersView.RowFilter = $"ParentRelations.{relationName} = '{selectedCustomerRow["CustomerID"]}'";

// Bind the filtered orders to another control (e.g., a second GridView)
ordersGridView.DataSource = ordersView;
ordersGridView.DataBind();
            

The ParentRelations. syntax within RowFilter is a powerful feature for dynamic filtering based on established relations.

< Previous: DataViews Next: Data Binding >