DataTable 條件約束
您可以使用條件約束,強制使用 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 | 將關聯資料列中的值設為預設值。 |
None | 不對關聯資料列採取任何動作。 這是預設值。 |
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 | 接受或拒絕子資料列的變更。 |
None | 不對子資料列採取任何動作。 這是預設值。 |
範例
下列範例會建立 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);