可以使用约束对DataTable中的数据强制实施限制,以保持数据的完整性。 约束是应用于列或相关列的自动规则,用于确定行值发生某种更改时的作过程。 当System.Data.DataSet.EnforceConstraints
属性DataSet为true时,约束被强制实施。 有关显示如何设置 EnforceConstraints
属性的代码示例,请参见 EnforceConstraints 参考主题。
ADO.NET 中有两种类型的约束: ForeignKeyConstraint 和 UniqueConstraint. 默认情况下,当在DataRelation中通过添加来创建两个或多个表之间的关系时,两个约束都会自动创建。 但是,可以通过在创建关系时指定 createConstraints = false 来禁用此行为。
ForeignKeyConstraint
ForeignKeyConstraint 强制实施有关如何传播相关表的更新和删除的规则。 例如,如果更新或删除了一行中的值,并且同一值也用于一个或多个相关表中, ForeignKeyConstraint 将确定相关表中发生的情况。
DeleteRule 的 UpdateRule 和 属性定义了用户尝试删除或更新相关表中的行时要执行的操作。 下表描述了 ForeignKeyConstraint 的 DeleteRule 和 UpdateRule 属性可用的不同设置。
规则设置 | DESCRIPTION |
---|---|
级联 | 删除或更新相关行。 |
SetNull | 将相关行中的值设置为 DBNull。 |
设置默认 | 将相关行中的值设置为默认值。 |
没有 | 对相关行不执行任何操作。 这是默认值。 |
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 方法取消更改。 当数据集包含 ForeignKeyConstraints 时,调用 AcceptChanges 或 RejectChanges 方法将强制实施 AcceptRejectRule。 ForeignKeyConstraint 中的 AcceptRejectRule 属性会在对父行调用 AcceptChanges 或 RejectChanges 时,确定对子行执行哪些操作。
下表列出了 AcceptRejectRule 的可用设置。
规则设置 | DESCRIPTION |
---|---|
级联 | 接受或拒绝对子行的更改。 |
没有 | 对子行不执行任何操作。 这是默认值。 |
示例:
以下示例创建一个 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 来为列创建唯一约束。 或者将单个列的唯一属性设置为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);