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:
- Navigate from a row in a parent table to its child rows.
- Navigate from a row in a child table to its corresponding parent row.
- Enforce referential integrity between related tables.
- Filter child rows based on the selected parent row.
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:
AcceptRejectRule
: Defines how changes are accepted or rejected whenAcceptChanges
is called.DeleteRule
: Specifies what happens to child rows when a parent row is deleted. Options includeCascade
(delete children),SetNull
(set child key columns to null), andNone
(allow deletion, potentially creating orphans).UpdateRule
: Specifies what happens to child rows when a parent row's key is updated. Similar options toDeleteRule
.
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.