表的架构或结构由列和约束表示。使用 DataColumn 对象以及 ForeignKeyConstraintUniqueConstraint 对象定义 DataTable 的架构。表中的列可以映射到数据源中的列、包含从表达式计算所得的值、自动递增它们的值,或包含主键值。

区分大小写

按名称引用表中的列、关系和约束是区分大小写的。一个表中可以存在两个或多个名称相同(但大小写不同)的列、关系或约束。例如,您可以有 Col1col1。在这种情况下,按名称引用某一列就必须完全符合该列名的大小写,否则会引发异常。例如,如果表 myTable 包含列 Col1 和列 col1,就要以 myTable.Columns["Col1"] 的形式来按名称引用 Col1,而以 myTable.Columns["col1"] 的形式按名称引用 col1。尝试以 myTable.Columns["COL1"] 的形式来引用其中某列就会产生异常。

如果对于某个特定名称只存在一个列、关系或约束,则不应用区分大小写规则。也就是说,如果表中没有其他的列、关系或约束对象与该特定列、关系或约束对象的名称一致,您就可以使用任意的大小写来按名称引用该对象,并且不会引发异常,即使大小写不同也无妨。例如,如果表中只有 Col1,您就可以使用 my.Columns["COL1"] 来引用它。

DataTable CaseSensitive 属性不会影响该行为。CaseSensitive 属性应用于表中的数据,并会影响排序、搜索、筛选、执行约束,等等。对表中的列、关系和约束的引用不会受 CaseSensitive 属性的影响。

本节内容

在表中添加列:说明如何使用 DataColumn 对象来定义表中的列。

DataTable 包含了由表的 Columns 属性引用的 DataColumn 对象的集合。这个列的集合与任何约束一起定义表的架构或结构。

通过使用 DataColumn 构造函数,或者通过调用表的 Columns 属性的 Add 方法(它是一个 DataColumnCollection),可在表内创建 DataColumn 对象。Add 方法将接受可选的 ColumnNameDataTypeExpression 参数,并将创建新的 DataColumn 作为集合的成员。它也会接受现有的 DataColumn 对象并会将其添至集合,如果有请求,将会返回对所添加 DataColumn 的引用。由于 DataTable 对象对任何数据源都不是特定的,所以在指定 DataColumn 的数据类型时会使用 .NET 框架类型。

以下示例将四列添至 DataTable

Dim workTable As DataTable = New DataTable("Customers")

Dim workCol As DataColumn = workTable.Columns.Add("CustID", Type.GetType("System.Int32"))
workColumn.AllowDBNull = false
workColumn.Unique = true

workTable.Columns.Add("CustLName", Type.GetType("System.String"))
workTable.Columns.Add("CustFName", Type.GetType("System.String"))
workTable.Columns.Add("Purchases", Type.GetType("System.Double"))

DataTable workTable = new DataTable("Customers");

DataColumn workCol = workTable.Columns.Add("CustID", typeof(Int32));
workCol.AllowDBNull = false;
workCol.Unique = true;

workTable.Columns.Add("CustLName", typeof(String));
workTable.Columns.Add("CustFName", typeof(String));
workTable.Columns.Add("Purchases", typeof(Double));

请注意,示例中用于 CustID 列的属性设置为不允许 DBNull 值并将值约束为唯一。但是,如果您将 CustID 列定义为表的主键列,AllowDBNull 属性就会自动设置为 false,并且 Unique 属性会自动设置为 true

警告 如果尚未给某列提供列名,则将该列添至 DataColumnCollection 时,该列会得到从“Column1”开始递增的默认名称 ColumnN。建议您在提供列名时避免使用“ColumnN”命名规则,因为您提供的名称可能会与 DataColumnCollection 中现有的默认列名冲突。如果提供的名称已经存在,将引发异常。

创建表达式列:说明如何使用列的 Expression 属性来计算值(根据行中其他列中的值)。

您可以为列定义表达式,让它能够包含根据同一行中其他列值或根据表中多行的列值计算而得的值。要定义对其进行计算的表达式,可使用目标列的 Expression 属性,并使用 ColumnName 属性在表达式中引用其他列。用于表达式列的 DataType 必须适合于表达式将返回的值。

下表列出了表中表达式列的几种可能用法。

表达式类型 示例
比较 “总计 >= 500”
计算 “单价×数量”
合计 总额(价格)

您可以在现有的 DataColumn 对象上设置 Expression 属性,或者可以包含作为第三个参数传递至 DataColumn 构造函数的属性,如下例所示。

workTable.Columns.Add("Total",Type.GetType("System.Double"))
workTable.Columns.Add("SalesTax", Type.GetType("System.Double"), "Total * 0.086")

workTable.Columns.Add("Total", typeof(Double));
workTable.Columns.Add("SalesTax", typeof(Double), "Total * 0.086");

表达式可以引用其他表达式列,但循环引用(其中两个表达式相互引用)将产生异常。有关编写表达式的规则,请参阅 DataColumn 类的 Expression 属性。

创建 AutoIncrement 列:说明如何将列设置为自动增加数值,以确保每行都有唯一的列值。

要确保列中的值唯一,可将列值设置为在表中添加新行时自动递增。要创建自动递增的 DataColumn,可将列的 AutoIncrement 属性设置为 true。然后,DataColumn 将从 AutoIncrementSeed 属性中定义的值开始,并且,随着各行的添加,AutoIncrement 列的值将按列的 AutoIncrementStep 属性中具有的值增加。

对于 AutoIncrement 列,建议您将 DataColumnReadOnly 属性设置为 true

以下示例演示了如何创建从值 200 开始并以三为增量进行添加的列。

Dim workColumn As DataColumn = workTable.Columns.Add("CustomerID", typeof(Int32))
workColumn.AutoIncrement = true
workColumn.AutoIncrementSeed = 200
workColumn.AutoIncrementStep = 3

DataColumn workColumn = workTable.Columns.Add("CustomerID", typeof(Int32));
workColumn.AutoIncrement = true;
workColumn.AutoIncrementSeed = 200;
workColumn.AutoIncrementStep = 3;

为表定义主键:说明如何从一个或多个 DataColumn 对象中指定表的主键。

数据库表通常都有一列或一组列,用于唯一地标识表中的每一行。这种具有标识作用的列或列组被称为主键。

在将一个单独的 DataColumn 标识为 DataTablePrimaryKey 时,表会自动将列的 AllowDBNull 属性设置为 false,并将 Unique 属性设置为 true。如果是多列主键,则只有 AllowDBNull 属性自动设置为 false

DataTablePrimaryKey 属性会将一个或多个 DataColumn 对象的数组接收为它的值,如下例所示。第一个示例将单独一列定义为主键。

workTable.PrimaryKey = New DataColumn() {workTable.Columns("CustID")}

' Or

Dim myColArray(1) As DataColumn
myColArray(0) = workTable.Columns("CustID")
workTable.PrimaryKey = myColArray

workTable.PrimaryKey = new DataColumn[] {workTable.Columns["CustID"]};

// Or

DataColumn[] myColArray = new DataColumn[1];
myColArray[0] = workTable.Columns["CustID"];
workTable.PrimaryKey = myColArray;

下面的示例将两列定义为主键。

workTable.PrimaryKey = New DataColumn() {workTable.Columns("CustLName"), _
                                         workTable.Columns("CustFName")}

' Or

Dim myKey(2) As DataColumn
myKey(0) = workTable.Columns("CustLName")
myKey(1) = workTable.Columns("CustFName")
workTable.PrimaryKey = myKey

workTable.PrimaryKey = new DataColumn[] {workTable.Columns["CustLName"], 
                                         workTable.Columns["CustFName"]};

// Or

DataColumn[] myKey = new DataColumn[2];
myKey[0] = workTable.Columns["CustLName"];
myKey[1] = workTable.Columns["CustFName"];
workTable.PrimaryKey = myKey;

将约束添加到表:说明如何为表中的列定义外键和唯一约束。

为了维护数据的完整性,可以使用 Constraints 来强制对 DataTable 中数据的限制。约束是应用于某列或相关各列的自动规则,它决定了某行的值以某种方式更改时的操作过程。当 DataSetEnforceConstraints 属性为 true 时,就可强制 Constraints

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

ForeignKeyConstraint

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

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

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

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

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

在创建 ForeignKeyConstraint 时,可将 DeleteRuleUpdateRule 值作为参数传递给构造函数,或者像下面示例中这样将它们设置为属性(其中 UpdateRule 值设为默认值,Cascade)。

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 方法接受对行的更改,或者使用 DataSetDataTableDataRowRejectChanges 方法取消对行的更改。DataSet 包含 ForeignKeyConstraints 时,调用 AcceptChangesRejectChanges 方法会导致强制 AcceptRejectRuleForeignKeyConstraint AcceptRejectRule 属性决定了对父行调用 AcceptChangesRejectChanges 时要对子行采取的操作。

下表列出了 AcceptRejectRule 可以设置的值。

操作 说明
Cascade 接受或拒绝对子行的更改。这是默认值。
None 指定不对子行采取任何操作。

UniqueConstraint

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

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

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

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

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