数据表约束

为了维护数据的完整性,可以使用约束来对 DataTable 中的数据施加限制。 约束是应用于某列或相关各列的自动规则,它决定了某行的值以某种方式更改时的操作过程。 当 DataSetSystem.Data.DataSet.EnforceConstraints 属性为 true 时,就可强制使用约束。 有关显示如何设置 EnforceConstraints 属性的代码示例,请参见 EnforceConstraints 参考主题。

ADO.NET 中有两种约束:ForeignKeyConstraintUniqueConstraint。 默认情况下,通过将 DataRelation 添加到 DataSet 来创建两个或多个表之间的关系时,两种约束都会自动创建。 但是,也可以在创建关系时,通过指定 createConstraints = false 禁用这一行为 = 。

ForeignKeyConstraint

ForeignKeyConstraint 强制使用有关如何对相关表所做更新和删除进行传播的规则。 例如,如果更新或删除了一个表的某行中的值,并且一个或多个相关的表中也使用了同样的值,ForeignKeyConstraint 会决定相关表中发生的操作。

ForeignKeyConstraint 的 DeleteRuleUpdateRule 属性定义在用户试图删除或更新相关表中某行时采取的操作。 下表描述可用于 ForeignKeyConstraint 的 DeleteRule 和 UpdateRule 属性的不同设置。

规则设置 说明
Cascade 删除或更新相关的行。
SetNull 将相关行中的值设置为 DBNull。
SetDefault 将相关行中的值设置为默认值。
对相关行不执行任何操作。 这是默认值。

ForeignKeyConstraint 可以限制并传播对相关列的更改。 根据为列的 ForeignKeyConstraint 设置的属性,并且如果 DataSet 的 EnforceConstraints 属性是 true,对父行执行某些特定操作将会导致异常。 例如,如果 ForeignKeyConstraint 的 DeleteRule 属性是 None,那么在父行有子行的情况下,则无法删除父行。

可以通过使用 ForeignKeyConstraint 构造函数创建单列间或一组列间的外键约束。 将生成的 ForeignKeyConstraint 对象传递给该表的 Constraints 属性的 Add 方法,该属性是一个 ConstraintCollection。 还可以将构造函数自变量传递给 ConstraintCollection 的 Add 方法的几个重载,以创建 ForeignKeyConstraint。

在创建 ForeignKeyConstraint 时,可以将 DeleteRule 和 UpdateRule 值作为自变量传递给构造函数,也可以作为属性进行设置,如以下示例所示(其中 DeleteRule 值设置为 None)。

Dim custOrderFK As ForeignKeyConstraint = New ForeignKeyConstraint("CustOrderFK", _  
  custDS.Tables("CustTable").Columns("CustomerID"), _  
  custDS.Tables("OrdersTable").Columns("CustomerID"))  
custOrderFK.DeleteRule = Rule.None
' Cannot delete a customer value that has associated existing orders.  
custDS.Tables("OrdersTable").Constraints.Add(custOrderFK)  
ForeignKeyConstraint custOrderFK = new ForeignKeyConstraint("CustOrderFK",  
  custDS.Tables["CustTable"].Columns["CustomerID"],
  custDS.Tables["OrdersTable"].Columns["CustomerID"]);  
custOrderFK.DeleteRule = Rule.None;
// Cannot delete a customer value that has associated existing orders.  
custDS.Tables["OrdersTable"].Constraints.Add(custOrderFK);  

AcceptRejectRule

可使用 AcceptChanges 方法接受对行的更改,或者使用 DataSet、DataTable 或 DataRow 的 RejectChanges 方法取消对行的更改。 DataSet 包含 ForeignKeyConstraints 时,调用 AcceptChanges 或 RejectChanges 方法会强制使用 AcceptRejectRule。 ForeignKeyConstraint 的 AcceptRejectRule 属性决定了对父行调用 AcceptChanges 或 RejectChanges 时要对子行执行的操作。

下表列出了 AcceptRejectRule 的可用设置。

规则设置 说明
Cascade 接受或拒绝对子行的更改。
对子行不执行任何操作。 这是默认值。

示例

下面的示例创建一个 ForeignKeyConstraint,设置它的一些属性(包括 AcceptRejectRule),并将它添加到 ConstraintCollection 对象的 DataTable

static void CreateConstraint(DataSet dataSet,
    string table1, string table2, string column1, string column2)
{
    // Declare parent column and child column variables.
    DataColumn parentColumn, childColumn;
    ForeignKeyConstraint foreignKeyConstraint;

    // Set parent and child column variables.
    parentColumn = dataSet.Tables[table1]?.Columns[column1] ??
        throw new NullReferenceException($"{nameof(CreateConstraint)}: {table1}.{column1} not found");
    childColumn = dataSet.Tables[table2]?.Columns[column2] ??
        throw new NullReferenceException($"{nameof(CreateConstraint)}: {table2}.{column2} not found");
    foreignKeyConstraint = new ForeignKeyConstraint
       ("SupplierForeignKeyConstraint", parentColumn, childColumn)
    {
        // Set null values when a value is deleted.
        DeleteRule = Rule.SetNull,
        UpdateRule = Rule.Cascade,
        AcceptRejectRule = AcceptRejectRule.None
    };

    // Add the constraint, and set EnforceConstraints to true.
    dataSet.Tables[table1]?.Constraints.Add(foreignKeyConstraint);
    dataSet.EnforceConstraints = true;
}
Private Sub CreateConstraint(dataSet As DataSet, _
   table1 As String, table2 As String, _
   column1 As String, column2 As String)

    ' Declare parent column and child column variables.
    Dim parentColumn As DataColumn
    Dim childColumn As DataColumn
    Dim foreignKeyConstraint As ForeignKeyConstraint

    ' Set parent and child column variables.
    parentColumn = dataSet.Tables(table1).Columns(column1)
    childColumn = dataSet.Tables(table2).Columns(column2)
    foreignKeyConstraint = New ForeignKeyConstraint _
       ("SupplierForeignKeyConstraint", parentColumn, childColumn)

    ' Set null values when a value is deleted.
    foreignKeyConstraint.DeleteRule = Rule.SetNull
    foreignKeyConstraint.UpdateRule = Rule.Cascade
    foreignKeyConstraint.AcceptRejectRule = AcceptRejectRule.None

    ' Add the constraint, and set EnforceConstraints to true.
    dataSet.Tables(table1).Constraints.Add(foreignKeyConstraint)
    dataSet.EnforceConstraints = True
End Sub

UniqueConstraint

UniqueConstraint 对象(可分配给 DataTable 中的单独一列或一组列)确保指定的某列或多个列中的所有数据对于每行都是唯一的。 通过使用 UniqueConstraint 构造函数,可以为一列或一组列创建唯一的约束。 将生成的 UniqueConstraint 对象传递给该表的 Constraints 属性的 Add 方法,该属性是一个 ConstraintCollection。 还可以将构造函数自变量传递给 ConstraintCollection 的 Add 方法的几个重载,以创建 UniqueConstraint。 为一列或多列创建 UniqueConstraint 时,可以选择指定此列或这些列是不是主键。

还可以通过将列的 Unique 属性设置为 true,为某列创建唯一约束。 或者,通过将单列的 Unique 属性设置为 false,可移除可能存在的任何唯一约束。 如果将一列或多列定义为表的主键,会自动为一个或多个指定的列创建唯一的约束。 如果从 DataTable 的 PrimaryKey 属性中移除一列,则 UniqueConstraint 也被移除。

以下示例为 DataTable 的两列创建 UniqueConstraint。

Dim custTable As DataTable = custDS.Tables("Customers")  
Dim custUnique As UniqueConstraint = _  
    New UniqueConstraint(New DataColumn()   {custTable.Columns("CustomerID"), _  
    custTable.Columns("CompanyName")})  
custDS.Tables("Customers").Constraints.Add(custUnique)  
DataTable custTable = custDS.Tables["Customers"];  
UniqueConstraint custUnique = new UniqueConstraint(new DataColumn[]
    {custTable.Columns["CustomerID"],
    custTable.Columns["CompanyName"]});  
custDS.Tables["Customers"].Constraints.Add(custUnique);  

请参阅