数据表约束
为了维护数据的完整性,可以使用约束来对 DataTable 中的数据施加限制。 约束是应用于某列或相关各列的自动规则,它决定了某行的值以某种方式更改时的操作过程。 当 DataSet 的 System.Data.DataSet.EnforceConstraints
属性为 true 时,就可强制使用约束。 有关显示如何设置 EnforceConstraints
属性的代码示例,请参见 EnforceConstraints 参考主题。
ADO.NET 中有两种约束:ForeignKeyConstraint 和 UniqueConstraint。 默认情况下,通过将 DataRelation 添加到 DataSet 来创建两个或多个表之间的关系时,两种约束都会自动创建。 但是,也可以在创建关系时,通过指定 createConstraints = false 禁用这一行为 = 。
ForeignKeyConstraint
ForeignKeyConstraint 强制使用有关如何对相关表所做更新和删除进行传播的规则。 例如,如果更新或删除了一个表的某行中的值,并且一个或多个相关的表中也使用了同样的值,ForeignKeyConstraint 会决定相关表中发生的操作。
ForeignKeyConstraint 的 DeleteRule 和 UpdateRule 属性定义在用户试图删除或更新相关表中某行时采取的操作。 下表描述可用于 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);