Every DataSet contains a DataRelationCollection object, which contains DataRelation objects. Each DataRelation defines a relationship between two tables. There are two reasons why you might define DataRelation objects:
To provide better error checking (for example, spotting an orphaned child before you reconnect to update the data source). This functionality is provided through the ForeignKeyConstraint, which the DataRelation can create implicitly.
To provide better navigation.
A typical DataRelation requires three pieces of information: a descriptive name of your choosing (which doesn't signify anything or relate to the data source), a reference to the parent DataColumn, and a reference to the child DataColumn. You can add this information with the DataRelation constructor:
DataRelation relation = new DataRelation("Name", ParentCol, ChildCol);
Once you've defined the DataRelation object, you need to add it to the DataSet:
For example, to create a relationship between product categories and products, use the following code:
DataColumn parentCol = ds.Tables["Categories"].Columns["CategoryID"]; DataColumn childCol = ds.Tables["Products"].Columns["CategoryID"]; DataRelation relation = new DataRelation("Cat_Prod", parentCol, childCol); ds.Relations.Add(relation);
If you attempt to create a DataRelation, and the parent record column isn't unique, or there are child records that refer to nonexistent parents, an exception is thrown.
At first glance, the DataRelation seems to duplicate some of the functionality provided by the ForeignKeyConstraint to enforce referential integrity. However, this isn't really the case. The DataRelation actually uses the Constraint classes. By default, when you create a new DataRelation, a UniqueConstraint is created automatically for the parent column and added to the parent table if it doesn't already exist. At the same time, a ForeignKeyConstraint is created for the child column and added to the child table. Thus, the rules governing relational integrity are exactly the same as those discussed in Chapter 10.
In some cases, you might want to create a DataRelation without generating any constraints. This allows you to use a relation to aid navigation but not enforce it as a data validation rule. One reason why you might not want to enforce a relationship could be because you have queried only a subset of the total parent rows in the data source. Consequently, there may be child rows that reference a valid parent row that isn't a part of the DataSet.
To make sure constraints are generated, you must use the DataRelation constructor that accepts an additional Boolean value. If you supply false, the Constraint objects aren't generated.
DataRelation relation = new DataRelation("Name", ParentCol, ChildCol, false);
You can still use the DataRelation for navigation, but referentially integrity will not be enforced on the DataSet.