VB.NET学习笔记:ADO.NET操作ACCESS数据库——在内存中构建数据库(DataSet数据集和DataTable数据表)

如有需要请参阅官方帮助:数据集、数据表和数据视图

ADO.NET DataSet 是数据的一种内存驻留表示形式,无论它包含的数据来自什么数据源,都会提供一致的关系编程模型。 DataSet 表示整个数据集(相当于实体的数据库),其中包含数据表(DataTable)、表间关系(DataRelation)和约束(Constraint)。我们完全可以通过编程的方式在内存中构建自己的数据库。

一、创建数据集(DataSet)

1、可以通过调用 DataSet 构造函数来创建 DataSet 的实例

如使用无参数构造函数:

Dim dst As New DataSet()
dst.DataSetName = "mydst"

或指定一个名称参数:

Dim dst As New DataSet("mydst")

这两种实例化DataSet得到的结果是一样的。
如果没有为 DataSet 指定名称,则该名称会设置为“NewDataSet”。如图:
默认的DataSet名称

2、也可以基于现有的 DataSet 来创建新的 DataSet

如:

        Dim dst As New DataSet("mydst")
        Dim dst1 As DataSet = dst

二、在数据集(DataSet)中管理数据表(DataTable)

可以通过DataSet对象的Tables属性管理数据表(DataTable)。
DataSet对象的Tables属性可以获取包含在 DataSet 中的表的集合(DataTableCollection)。如果 DataTable 对象不存在,将返回空集合。

1、将数据表添加到数据集中

若要将表添加到DataSet中,可以使用DataTableCollection集合的Add方法。如图:
将数据表添加到数据集中

(1)、使用无参数的Add方法

示例代码源自官网源码改编:

Dim table As DataTable

        Dim thisDataSet As New DataSet()
        Dim i As Integer
        For i = 0 To 2
            thisDataSet.Tables.Add()
        Next i

        Dim strshow As String = thisDataSet.Tables.Count.ToString() & " tables" & Environment.NewLine & "TableName" & Environment.NewLine
        For Each table In thisDataSet.Tables
            strshow &= table.TableName & Environment.NewLine
        Next
        MessageBox.Show(strshow)

因为不指定任何名称,所以DataTable使用默认名称,根据其添加顺序, 默认名称为"Table1"、“Table2”……。如图:
DataTable的默认名称

(2)、Add(DataTable)方法

首先需要实例化DataTable对象。与创建 DataSet 一样,可以通过调用 DataTable构造函数来创建DataTable的实例。
如使用无参数构造函数:

Dim dt As New DataTable()
dt.TableName = "mytable"

或指定表名:

Dim dt As New DataTable("mytable")

效果是一样的,如果没有指定表名,则其表名为空字符串。
当然也可以基于现有的 DataTable 来创建新的DataTable实例。

       Dim dt As New DataTable("mytable")
        Dim dt1 As DataTable = dt

获得DataTable的实例后,就可以把该实例添加到DataSet中。

        Dim dt As New DataTable("mytable")
        Dim dst As New DataSet()
        dst.Tables.Add(dt)

(3)、Add(String)方法

Add(String)方法使用指定名称创建一个 DataTable 对象,并将其添加到DataSet中。如:

        Dim dst As New DataSet()
        dst.Tables.Add("mytable")

2、将数据表从数据集中移除

(1)、移除指定的 DataTable 对象

使用DataTableCollection集合的Remove方法可以移除指定的 DataTable 对象。

Dim dt As New DataTable("mytable")
        Dim dst As New DataSet()
        dst.Tables.Add(dt)
        dst.Tables.Add("mytable1")
        
        If dst.Tables.Contains("mytable1") And dst.Tables.CanRemove(dst.Tables("mytable1")) Then
            dst.Tables.Remove("mytable1") '参数为表名称的字符串
        End If

        If dst.Tables.Contains(dt.TableName) And dst.Tables.CanRemove(dst.Tables(dt.TableName)) Then
            dst.Tables.Remove(dt) '参数为DataTable对象
        End If

代码中使用Contains方法判断该表名是否存在和CanRemove方法判断该表是否可以移除,再进行移除,防止出错。

(2)、清除所有 DataTable 对象

使用DataTableCollection集合的Clear方法可以一次性清除所有 DataTable 对象且不会引发错误。

dst.Tables.Clear()

三、定义表结构

1、在数据表中管理列

使用DataTable对象的Columns属性来管理列(DataColumn 对象),DataTable对象的Columns属性值是一个 DataColumnCollection,包含该表的 DataColumn 对象的集合。

(1)、向数据表中添加列

使用DataColumnCollection集合的Add方法向数据表添加列,Add有多个重载的版本。如:
向数据表中添加列的Add方法

A、使用Add()或Add()或Add(DataColumn)方法

必须先实例化一个 DataColumn 对象。 DataColumn 对象有多个构造函数,如:
DataColumn 对象的构造函数
通过构造函数初始化DataColumn 对象的一些属性,如:数据的类型(DataType)、列的名称(ColumnName)等。
示例代码先取得DataColumn实例,再用Add方法将DataColumn实例添加到DataTable对象中:

Dim dt As New DataTable("mytable")

        Dim colstring As New DataColumn()
        colstring.DataType = Type.GetType("System.String")
        colstring.ColumnName = "stringcol"
        dt.Columns.Add(colstring)

        Dim colInt32 As DataColumn = New DataColumn("Int32Col", Type.GetType("System.Int32"))
        dt.Columns.Add(colInt32)

B、使用Add(String)或Add(String, Type)方法

不需要取得DataColumn实例,而是向Add方法传入参数,在方法内部自行构造DataColumn实例。可以使代码更简洁,如:

        Dim dt As New DataTable("mytable")
        dt.Columns.Add("BooleanCol").DataType = Type.GetType("System.Boolean")
        dt.Columns.Add("BooleanCol", Type.GetType("System.Boolean"))

这两个Add方法添加列效果是一样的。

(2)、在数据表中移除列

A、移除指定列

Remove(DataColumn)方法可以移除指定的 DataColumn 对象。
Remove(String) 方法可以移除具有指定名称的 DataColumn 对象。

Dim dt As New DataTable("mytable")

        Dim colstring As New DataColumn()
        colstring.DataType = Type.GetType("System.String")
        colstring.ColumnName = "stringcol"
        dt.Columns.Add(colstring)

        Dim colInt32 As DataColumn = New DataColumn("Int32Col", Type.GetType("System.Int32"))
        dt.Columns.Add(colInt32)

        If dt.Columns.Contains(colstring.ColumnName) And dt.Columns.CanRemove(colstring) Then
            dt.Columns.Remove(colstring)
        End If

        If dt.Columns.Contains("Int32Col") And dt.Columns.CanRemove(dt.Columns("Int32Col")) Then
            dt.Columns.Remove("Int32Col")
        End If

本示例代码先添加列,然后使用Contains方法,确定是否存在已命名的列。 再用 CanRemove方法检查是否可以删除列,如果满足则使用Remove方法将其删除。

B、移除全部列

使用DataColumnCollection的Clear方法可以一次性清除全部列而不会引发错误。

dt.Columns.Clear()

(3)、添加表达式列

使用DataColumn对象的Expression 属性设置表达式,如下代码直接将Expression 属性值用作第三个参数传递给DataColumn构造函数:

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

可以使用 ColumnName 属性在表达式中引用其他列(Total),需要注意的是用于表达式列的 DataType 必须适合于表达式将返回的值(即Total列和SalesTax列的数据类型应该一致),还要注意不能循环引用列,否则会引发异常。

(4)、添加自动递增列

若要创建自动递增列,需将DataColumn对象的AutoIncrement属性值设置为true。 并利用AutoIncrementSeed属性设置起始值(默认值为 0),利用AutoIncrementStep属性设置自动递增的数值(默认值为 1)。同时最好把ReadOnly属性设置为true。
以下示例演示了如何创建从值 200 开始并以 3 为增量递增的列。

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

2、定义数据表约束

(1)、定义主键

使用DataTable对象的PrimaryKey属性获取或设置用作数据表主键的列数组。
特别注意,DataTable对象的PrimaryKey属性接收作为其值的一个或多个DataColumn对象的数组,也就是说其值是一个数据类型为DataColumn的数组。
以下示例将单独一列设置为主键:

dt.PrimaryKey = New DataColumn() {workTable.Columns("CustID")}  
  
' Or  
  
Dim columns(1) As DataColumn  
columns(0) = workTable.Columns("CustID")  
dt.PrimaryKey = columns  

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

workTable.PrimaryKey = New DataColumn() {workTable.Columns("CustLName"), _  
                                         workTable.Columns("CustFName")}  
  
' Or  
  
Dim keyColumn(2) As DataColumn  
keyColumn(0) = workTable.Columns("CustLName")  
keyColumn(1) = workTable.Columns("CustFName")  
workTable.PrimaryKey = keyColumn

(2)、空值约束

使用DataColumn对象的AllowDBNull属性获取或设置一个值,该值指示对于属于该表的行,此列中是否允许空值。如果允许空值,则为 true;否则为 false。 默认值为 true。
下面的示例创建一个新DataColumn,并设置其AllowDBNull属性设置为true。

Private Sub AddNullAllowedColumn()
    Dim column As DataColumn
    column = New DataColumn("classID", _
        System.Type.GetType("System.Int32"))
    column.AllowDBNull = True

    ' Add the column to a new DataTable.
    Dim table As DataTable
    table = New DataTable
    table.Columns.Add(column)
End Sub

(3)、默认值约束

使用DataColumn对象的DefaultValue属性在创建新行时获取或设置列的默认值。
下面的示例将创建多个数据类型不同的DataColumn对象,并为每个列设置相应默认值。

Private Sub CreateColumns()
    Dim column As DataColumn
    Dim table As New DataTable
 
    column = New DataColumn
    With column
       .DataType = System.Type.GetType("System.String")
       .DefaultValue = "Address"
       .Unique = False
    End With
    table.Columns.Add(column)
    
    column = New DataColumn
    With column
       .DataType = System.Type.GetType("System.Int32")
       .DefaultValue = 100
    End With
    table.Columns.Add(column)
 
    column = New DataColumn
    With column
       .DataType = System.Type.GetType("System.DateTime")
       .DefaultValue = "1/1/2001"
    End With
    table.Columns.Add(column)
 
    Dim row As DataRow
    ' Add one row. Since it has default values, 
    ' no need to set values yet.
    row = table.NewRow
   
    table.Rows.Add(row)
 End Sub

(4)、唯一约束

可以使用DataColumn对象的Unique属性获取或设置一个值,该值指示列的每一行中的值是否必须是唯一的。如果值必须是唯一的,则为 true;否则为 false。 默认值为 false。如:

 Private Sub AddColumn(table As DataTable)
        Dim column As DataColumn = New DataColumn("Total")
        column.DataType = System.Type.GetType("System.Decimal")
        column.ReadOnly = True '只读
        column.Expression = "UnitPrice * Quantity" '表达式
        column.Unique = False '唯一约束
End Sub

如果要对多个列集合定义唯一约束,应该使用UniqueConstraint类,UniqueConstraint类有多个构造函数进行实例化。通常使用UniqueConstraint(String, DataColumn)构造函数为单列定义唯一约束,使用UniqueConstraint(String, DataColumn[])构造函数为多列集合定义唯一约束。然后使用ConstraintCollection对象的Add方法将约束添加到表中(DataTable对象的Constraints属性可以获得一个 ConstraintCollection,包含该表的 Constraint 对象的集合)。
单独列的唯一约束:

Private Sub CreateUniqueConstraint(ByVal dataSetSuppliers As DataSet)
        Dim uniqueConstraint As UniqueConstraint
        Dim dataColumn As DataColumn
        dataColumn = dataSetSuppliers.Tables("Suppliers").Columns("SupplierID")

        uniqueConstraint = New UniqueConstraint("supplierIdConstraint", dataColumn)

        dataSetSuppliers.Tables("Suppliers").Constraints.Add(uniqueConstraint)
    End Sub

多列的唯一约束:

Private Sub AddUniqueConstraint(ByVal dataTable As DataTable)
        Dim dataColumns(1) As DataColumn
        dataColumns(0) = dataTable.Columns("ID")
        dataColumns(1) = dataTable.Columns("Name")

        Dim uniqueConstraint As New UniqueConstraint("idNameConstraint", dataColumns)
        dataTable.Constraints.Add(uniqueConstraint)
    End Sub

(5)、定义外键

通过创建ForeignKeyConstraint类来定义外键。ForeignKeyConstraint(String, DataColumn, DataColumn)构造函数可以创建单列的外键关系,ForeignKeyConstraint(String, DataColumn[], DataColumn[])构造函数可以创建多列的外键关系。
下面的示例创建一个新ForeignKeyConstraint,设置的某些属性,并将其添加到DataTable对象的ConstraintCollection。

  Private suppliersProducts As SuppliersProducts

Private Sub CreateConstraint()
  
   Dim parentColumn As DataColumn
   Dim childColumn As DataColumn
   Dim fkeyConstraint As ForeignKeyConstraint

   parentColumn = _
       suppliersProducts.Tables("Suppliers").Columns("SupplierID")
   childColumn = _
       suppliersProducts.Tables("Products").Columns("SupplierID")
   fkeyConstraint = New ForeignKeyConstraint( _
       "SupplierFKConstraint", parentColumn, childColumn)

   With fkeyConstraint
      .DeleteRule = Rule.SetNull
      .UpdateRule = Rule.Cascade
      .AcceptRejectRule = AcceptRejectRule.Cascade
   End With

   suppliersProducts.Tables("Products").Constraints.Add(fkeyConstraint)
   suppliersProducts.EnforceConstraints = True
End Sub

或多列:

Private Sub CreateConstraint(ByVal suppliersProducts As DataSet)
    Dim parentColumns(1) As DataColumn
    Dim childColumns(1) As DataColumn
    Dim fkConstraint As ForeignKeyConstraint
.
    parentColumns(0) = _
        suppliersProducts.Tables("OrderDetails").Columns("OrderID")
    parentColumns(1) = _
        suppliersProducts.Tables("OrderDetails").Columns("ProductID")
    childColumns(0) = _
        suppliersProducts.Tables("Sales").Columns("OrderID")
    childColumns(1) = _
        suppliersProducts.Tables("Sales").Columns("ProductID")
    fkConstraint = New ForeignKeyConstraint( _
        "ProductSalesOrders", parentColumns, childColumns)

    With fkConstraint
        .DeleteRule = Rule.SetDefault
        .UpdateRule = Rule.Cascade
        .AcceptRejectRule = AcceptRejectRule.Cascade
    End With

    suppliersProducts.Tables("OrderDetails").Constraints.Add( _
        fkConstraint)
    suppliersProducts.EnforceConstraints = True
End Sub

说明 :
A、DataSet对象的EnforceConstraints属性可以获取或设置一个值,该值指示在尝试执行任何更新操作时是否遵循约束规则。如果强制执行规则为true ;否则为false。 默认值为 true。
B、ForeignKeyConstraint类的DeleteRule和UpdateRule属性可以定义当用户尝试删除或更新相关表中的行时采取的操作。
规则设置 描述
Cascade 删除或更新相关的行。
SetNull 在相关的行中设置值DBNull。
SetDefault 将相关行中的值设置为默认值。
None 对相关行不执行任何操作。 这是默认设置。
C、ForeignKeyConstraint类的AcceptRejectRule属性调用AcceptChanges或RejectChanges方法时采取的操作。
规则设置 描述
Cascade 接受或拒绝对子行的更改。
None 对子行不执行任何操作。 这是默认设置。

(6)、添加 DataRelation关系

表示两个 DataTable 对象之间的父/子关系。下面的示例创建一个新DataRelation并将其添加到DataSet对象的DataRelationCollection集合中。

Private Sub CreateRelation()
    ' Get the DataColumn objects from two DataTable objects 
    ' in a DataSet. Code to get the DataSet not shown here.
    Dim parentColumn As DataColumn = _
        DataSet1.Tables("Customers").Columns("CustID")
    Dim childColumn As DataColumn = DataSet1.Tables( _
        "Orders").Columns("CustID")

    ' Create DataRelation.
    Dim relCustOrder As DataRelation
    relCustOrder = New DataRelation( _
        "CustomersOrders", parentColumn, childColumn)

    ' Add the relation to the DataSet.
    DataSet1.Relations.Add(relCustOrder)
End Sub

(7)、移除约束

ConstraintCollection.Remove方法可以移除指定的约束,参数可以为 Constraint对象或 Constraint对象的名称字符串。

Private Sub RemoveConstraint(table As DataTable, _
    constraint As Constraint)

    If table.Constraints.Contains(constraint.ConstraintName) Then
        If table.Constraints.CanRemove(constraint) Then
            table.Constraints.Remove(constraint)
        End If
    End If
End Sub

Private Sub RemoveConstraint _
    (constraints As ConstraintCollection, constraint As Constraint)

    If constraints.Contains(constraint.ConstraintName) Then
        If constraints.CanRemove(constraint) Then
            constraints.Remove(constraint.ConstraintName)
        End If
    End If
End Sub

使用Remove方法之前,可以使用Contains方法,以确定集合是否包含目标Constraint,用CanRemove方法,以确定Constraint是否可以删除。
ConstraintCollection.RemoveAt(Int32)方法可以移除指定索引号的约束。下面的示例使用IndexOf一起使用的方法RemoveAt方法中删除的约束ConstraintCollection。

Private Sub RemoveConstraint _
    (constraints As ConstraintCollection, constraint As Constraint)

    Try
        If constraints.Contains(constraint.ConstraintName) Then
            If constraints.CanRemove(constraint) Then
                constraints.RemoveAt _
                    (constraints.IndexOf(constraint.ConstraintName))
            End If
        End If

    Catch e As Exception
        ' Process exception and return.
        Console.WriteLine("Exception of type {0} occurred.", _
            e.GetType().ToString())
    End Try
End Sub

ConstraintCollection.Clear方法可以一次性清除所有的约束。

Public Shared Sub ClearConstraints(dataSet As DataSet) 
   Dim table As DataTable
   For Each table In dataSet.Tables
     table.Constraints.Clear()
   Next
End Sub

四、大小写规则

DataSet 中可以存在两个或两个以上的同名但是大小写不同的表、关系或约束。 在这种情况下,通过名称对表、关系或约束的引用将区分大小写。 例如,如果DataSet数据集包含表Table1和table1,正确的引用为dataSet.Tables[“Table1”]和dataSet.Tables[“table1”]。 而dataSet.Tables[“TABLE1”] 会生成异常。
但如果只有一个具有特定名称的表、关系或约束,则不区分大小写。 例如,如果DataSet只有Table1,您可以使用dataSet.Tables[“TABLE1”]引用它。

五、命名空间支持

在 2.0 之前的 ADO.NET 版本中,两个表即使处于不同的命名空间中也不能同名。 ADO.NET 2.0 中取消了此限制。 DataSet 可以包含具有相同 TableName 属性值但是具有不同 Namespace 属性值的两个表。
到此,一个内存数据库框架已经搭建完成。

猜你喜欢

转载自blog.csdn.net/zyjq52uys/article/details/88633900