The System.Data.Constraint
type is an abstract
class with two derived classes: UniqueConstraint
and ForeignKeyConstraint
. In order to use a
constraint, you must create the appropriate class and add it to the
DataTable.Constraints
collection.
Constraints are enforced only if the
EnforceConstraints
property of the containing
DataSet
is true
, which it is by
default. If you attempt to modify, delete, or insert data in such a
way that it violates an existing constraint, and
EnforceConstraints
is true
, a
ConstraintException
is thrown, and the change is rejected.
Similarly, if the DataTable
already contains data,
and you add a new Constraint
, all the rows are
checked to ensure they agree with the new rule. If any row violates
the constraint, an InvalidConstraintException
is
thrown, and the Constraint
object
isn’t added.
Here are a few more rules of thumb that come into play when working
with Constraint
objects:
If you have set DataSet.EnforceConstraints
to
false
, you will never encounter a
ConstraintException
or
InvalidConstraintException
. However, if you later change
DataSet.EnforceConstraints
to
true
, all the rows will be examined to ensure that
they don’t violate the existing constraints. If a
discrepancy is found, an
InvalidConstraintException
is thrown, and
EnforceConstraints
is set to
false
.
When merging a DataSet
,
constraints are applied and verified after
the merge is complete.
There is no limit to how many Constraint
objects a
DataTable
can contain; you are free to define as
many unique rows and foreign key restrictions as you need.
It doesn’t seem possible for .NET developers to
create custom .NET constraint classes. The
Constraint
object defines several abstract methods
that have assembly-level protection, so they can be overridden only
by classes in the System.Data.dll
assembly.
However, you can create a class that handles the
DataTable.ColumnChanging
event to implement custom
validation, as explained in Chapter 7.