配置数据访问层的连接和命令级别的设置 (VB)

作者 :Scott Mitchell

下载 PDF

类型化数据集中的 TableAdapter 会自动处理连接到数据库、发出命令以及使用结果填充 DataTable 的操作。 但是,在某些情况下,我们希望自行处理这些详细信息,在本教程中,我们将了解如何访问 TableAdapter 中的数据库连接和命令级设置。

简介

在整个教程系列中,我们使用了类型化数据集来实现分层体系结构的数据访问层和业务对象。 如 第一篇教程中所述,类型化数据集的 DataTable 充当数据的存储库,而 TableAdapter 充当与数据库通信以检索和修改基础数据的包装器。 TableAdapter 封装了使用数据库所涉及的复杂性,无需编写代码来连接到数据库、发出命令或将结果填充到 DataTable 中。

但是,有时我们需要钻取到 TableAdapter 的深度,并编写直接处理 ADO.NET 对象的代码。 例如,在 事务中包装数据库修改 教程中,我们向 TableAdapter 添加了用于开始、提交和回滚 ADO.NET 事务的方法。 这些方法使用了分配给 TableAdapter 对象SqlCommand的内部手动创建SqlTransaction的对象。

在本教程中,我们将了解如何访问 TableAdapter 中的数据库连接和命令级设置。 具体而言,我们将向 添加功能ProductsTableAdapter,以便访问基础连接字符串和命令超时设置。

使用 ADO.NET 处理数据

Microsoft .NET Framework包含大量专为处理数据而设计的类。 命名空间中的System.Data这些类称为 ADO.NET 类。 ADO.NET 保护伞下的某些类与特定 数据提供程序相关联。 可以将数据提供程序视为允许信息在 ADO.NET 类和基础数据存储之间流动的信道。 有通用的提供程序(如 OleDb 和 ODBC),以及专为特定数据库系统设计的提供程序。 例如,虽然可以使用 OleDb 提供程序连接到 Microsoft SQL Server 数据库,但 SqlClient 提供程序的效率要高得多,因为它专为SQL Server而设计和优化。

以编程方式访问数据时,通常使用以下模式:

  1. 与数据库建立连接。
  2. 发出命令。
  3. 对于 SELECT 查询,请使用生成的记录。

有单独的 ADO.NET 类用于执行其中每个步骤。 例如,若要使用 SqlClient 提供程序连接到数据库,请使用 SqlConnection。 若要向 INSERT数据库发出 、 UPDATEDELETESELECT 命令,请使用 SqlCommand

除了在 事务中包装数据库修改 教程外,我们不必自行编写任何低级别 ADO.NET 代码,因为 TableAdapters 自动生成的代码包括连接到数据库、发出命令、检索数据以及将数据填充到 DataTables 所需的功能。 但是,有时我们可能需要自定义这些低级别设置。 在接下来的几个步骤中,我们将检查如何利用 TableAdapters 在内部使用的 ADO.NET 对象。

步骤 1:使用 Connection 属性检查

每个 TableAdapter 类都有一个 Connection 指定数据库连接信息的属性。 此属性的数据类型和 ConnectionString 值由 TableAdapter 配置向导中的选择确定。 回想一下,当我们第一次将 TableAdapter 添加到类型化数据集时,此向导会要求我们提供数据库源 (见图 1) 。 第一步中的下拉列表包括配置文件中指定的数据库,以及服务器资源管理器数据Connections中的任何其他数据库。 如果下拉列表中不存在要使用的数据库,可以通过单击“新建连接”按钮并提供所需的连接信息来指定新的数据库连接。

TableAdapter 配置向导的第一步

图 1:TableAdapter 配置向导的第一步 (单击以查看全尺寸图像)

让我们花点时间检查 TableAdapter 属性的代码 Connection 。 如 创建数据访问层 教程中所述,我们可以通过转到“类视图”窗口,向下钻取到相应的类,然后双击成员名称来查看自动生成的 TableAdapter 代码。

转到“视图”菜单并选择“类视图” (或通过键入 Ctrl+Shift+C) 导航到“类视图”窗口。 在“类视图”窗口的上半部分,向下钻取到 NorthwindTableAdapters 命名空间并选择类 ProductsTableAdapter 。 这将在 ProductsTableAdapter 类视图的下半部分显示 成员,如图 2 所示。 双击属性 Connection 以查看其代码。

双击类视图中的 Connection 属性以查看其自动生成的代码

图 2:Double-Click 类视图中的 Connection 属性以查看其自动生成的代码

TableAdapter 属性 Connection 和其他与连接相关的代码如下所示:

Private _connection As System.Data.SqlClient.SqlConnection
Private Sub InitConnection()
    Me._connection = New System.Data.SqlClient.SqlConnection
    Me._connection.ConnectionString = _
        ConfigurationManager.ConnectionStrings("NORTHWNDConnectionString").ConnectionString
End Sub
Friend Property Connection() As System.Data.SqlClient.SqlConnection
    Get
        If (Me._connection Is Nothing) Then
            Me.InitConnection
        End If
        Return Me._connection
    End Get
    Set
        Me._connection = value
        If (Not (Me.Adapter.InsertCommand) Is Nothing) Then
            Me.Adapter.InsertCommand.Connection = value
        End If
        If (Not (Me.Adapter.DeleteCommand) Is Nothing) Then
            Me.Adapter.DeleteCommand.Connection = value
        End If
        If (Not (Me.Adapter.UpdateCommand) Is Nothing) Then
            Me.Adapter.UpdateCommand.Connection = value
        End If
        Dim i As Integer = 0
        Do While (i < Me.CommandCollection.Length)
            If (Not (Me.CommandCollection(i)) Is Nothing) Then
                CType(Me.CommandCollection(i), _
                    System.Data.SqlClient.SqlCommand).Connection = value
            End If
            i = (i + 1)
        Loop
    End Set
End Property

实例化 TableAdapter 类时,成员变量 _connection 等于 NothingConnection访问 属性时,它首先检查成员变量是否已_connection实例化。 如果没有,InitConnection则调用 方法,以实例化_connection并将其 ConnectionString 属性设置为 TableAdapter 配置向导第一步中指定的连接字符串值。

还可以 Connection 将 属性分配给 SqlConnection 对象。 这样做会将新 SqlConnection 对象与每个 TableAdapter 对象 SqlCommand 相关联。

步骤 2:公开 Connection-Level 设置

连接信息应保持封装在 TableAdapter 中,应用程序体系结构中的其他层无法访问。 但是,在某些情况下,需要为查询、用户或 ASP.NET 页面访问或自定义 TableAdapter 的连接级信息。

让我们扩展 ProductsTableAdapter DataSet 中的 Northwind ,以包含一个ConnectionString属性,业务逻辑层可以使用该属性来读取或更改 TableAdapter 使用的连接字符串。

注意

连接字符串是一个字符串,用于指定数据库连接信息,例如要使用的提供程序、数据库的位置、身份验证凭据和其他与数据库相关的设置。 有关各种数据存储和提供程序使用的连接字符串模式的列表,请参阅 ConnectionStrings.com

创建数据访问层 教程中所述,通过使用分部类可以扩展类型化数据集自动生成的类。 首先,在项目的文件夹下~/App_Code/DAL创建一个名为 ConnectionAndCommandSettings 的新子文件夹。

添加名为 ConnectionAndCommandSettings 的子文件夹

图 3:添加名为 的子文件夹 ConnectionAndCommandSettings

添加名为 ProductsTableAdapter.ConnectionAndCommandSettings.vb 的新类文件并输入以下代码:

Namespace NorthwindTableAdapters
    Partial Public Class ProductsTableAdapter
        Public Property ConnectionString() As String
            Get
                Return Me.Connection.ConnectionString
            End Get
            Set(ByVal value As String)
                Me.Connection.ConnectionString = value
            End Set
        End Property
    End Class
End Namespace

此分部类将名为 ConnectionString 的属性添加到 Public 类,ProductsTableAdapter该类允许任何层读取或更新 TableAdapter 基础连接的连接字符串。

将此分部类创建 (并保存) 后,打开 ProductsBLL 类。 转到现有方法之一并键入 Adapter ,然后按句点键调出 IntelliSense。 应会看到 IntelliSense 中提供的新 ConnectionString 属性,这意味着可以通过编程方式从 BLL 读取或调整此值。

公开整个连接对象

此分部类只公开基础连接对象的一个属性: ConnectionString。 如果要使整个连接对象超出 TableAdapter 的范围可用,也可以更改 Connection 属性的保护级别。 我们在步骤 1 中检查的自动生成的代码显示 TableAdapter 的 Connection 属性被标记为 Friend,这意味着它只能由同一程序集中的类访问。 但是,这可以通过 TableAdapter 的 ConnectionModifier 属性进行更改。

打开Northwind数据集,单击ProductsTableAdapterDesigner中的 ,然后导航到属性窗口。 你将看到 设置为 ConnectionModifier 其默认值 Assembly的 。 若要使 Connection 属性在类型化数据集程序集之外可用,请将 属性 ConnectionModifier 更改为 Public

可以通过 ConnectionModifier 属性配置 Connection 属性的辅助功能级别

图 4Connection 可通过属性配置 ConnectionModifier 属性辅助功能级别 (单击以查看全尺寸图像)

保存 DataSet,然后返回到 ProductsBLL 类。 与之前一样,转到现有方法之一并键入 Adapter ,然后按句点键来调出 IntelliSense。 列表应包含 属性 Connection ,这意味着你现在可以以编程方式从 BLL 读取或分配任何连接级设置。

TableAdapter 由main查询组成,默认情况下,该查询具有自动生成的 INSERTUPDATEDELETE 语句。 此main查询 INSERTUPDATEDELETE 语句通过 Adapter 属性在 TableAdapter 代码中作为 ADO.NET 数据适配器对象实现。 与其 Connection 属性一样, Adapter 属性的数据类型由使用的数据提供程序确定。 由于这些教程使用 SqlClient 提供程序,因此 属性 Adapter 的类型 SqlDataAdapter为 。

TableAdapter 属性 Adapter 具有三个类型的 SqlCommand 属性,用于发出 INSERTUPDATEDELETE 语句:

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

SqlCommand对象负责将特定查询发送到数据库,并且具有以下属性:CommandText,其中包含要执行的即席 SQL 语句或存储过程;和 Parameters,它是 对象的集合SqlParameter。 正如我们在创建数据访问层教程中看到的那样,可以通过属性窗口自定义这些命令对象。

除了main查询之外,TableAdapter 还可以包含可变数目的方法,在调用这些方法时,可将指定的命令调度到数据库。 main查询 命令对象和所有其他方法的命令对象存储在 TableAdapter 的 CommandCollection 属性中。

让我们花点时间看看 DataSet 中Northwind为这两个属性及其支持成员变量和帮助程序方法生成的ProductsTableAdapter代码:

Private WithEvents _adapter As System.Data.SqlClient.SqlDataAdapter
Private Sub InitAdapter()
    Me._adapter = New System.Data.SqlClient.SqlDataAdapter
    
    ... Code that creates the InsertCommand, UpdateCommand, ...
    ... and DeleteCommand instances - omitted for brevity ...
End Sub
Private ReadOnly Property Adapter() As System.Data.SqlClient.SqlDataAdapter
    Get
        If (Me._adapter Is Nothing) Then
            Me.InitAdapter
        End If
        Return Me._adapter
    End Get
End Property
Private _commandCollection() As System.Data.SqlClient.SqlCommand
Private Sub InitCommandCollection()
    Me._commandCollection = New System.Data.SqlClient.SqlCommand(8) {}
    ... Code that creates the command objects for the main query and the ...
    ... ProductsTableAdapter�s other eight methods - omitted for brevity ...
End Sub
Protected ReadOnly Property CommandCollection() As System.Data.SqlClient.SqlCommand()
    Get
        If (Me._commandCollection Is Nothing) Then
            Me.InitCommandCollection
        End If
        Return Me._commandCollection
    End Get
End Property

CommandCollection 属性的代码Adapter与 属性的代码Connection非常接近。 存在一些成员变量,用于保存属性使用的对象。 属性 Get 访问器首先检查相应的成员变量是否为 Nothing。 如果是这样,则调用初始化方法,该方法创建成员变量的实例并分配与命令相关的核心属性。

步骤 4:公开 Command-Level 设置

理想情况下,命令级信息应仍封装在数据访问层中。 但是,如果体系结构的其他层需要此信息,可以通过分部类公开此信息,就像使用连接级别设置一样。

由于 TableAdapter 只有一 Connection 个属性,因此用于公开连接级别设置的代码相当简单。 修改命令级设置时,事情会稍微复杂一些,因为 TableAdapter 可以有多个命令对象 - 一个 InsertCommandUpdateCommandDeleteCommand,以及 属性中 CommandCollection 可变数量的命令对象。 更新命令级设置时,需要将这些设置传播到所有命令对象。

例如,假设 TableAdapter 中的某些查询执行时间非常长。 使用 TableAdapter 执行其中一个查询时,我们可能需要增加命令对象的 属性CommandTimeout。 此属性指定等待命令执行的秒数,默认值为 30。

若要允许 CommandTimeout BLL 调整 属性,请使用步骤 2 (ProductsTableAdapter.ConnectionAndCommandSettings.vb) 中创建的分部类文件将ProductsDataTable以下Public方法添加到 中:

Public Sub SetCommandTimeout(ByVal timeout As Integer)
    If Me.Adapter.InsertCommand IsNot Nothing Then
        Me.Adapter.InsertCommand.CommandTimeout = timeout
    End If
    If Me.Adapter.DeleteCommand IsNot Nothing Then
        Me.Adapter.DeleteCommand.CommandTimeout = timeout
    End If
    If Me.Adapter.UpdateCommand IsNot Nothing Then
        Me.Adapter.UpdateCommand.CommandTimeout = timeout
    End If
    For i As Integer = 0 To Me.CommandCollection.Length - 1
        If Me.CommandCollection(i) IsNot Nothing Then
            Me.CommandCollection(i).CommandTimeout = timeout
        End If
    Next
End Sub

可以从 BLL 或表示层调用此方法,为该 TableAdapter 实例的所有命令问题设置命令超时。

注意

AdapterCommandCollection 属性标记为 Private,这意味着只能从 TableAdapter 中的代码访问它们。 Connection与 属性不同,这些访问修饰符不可配置。 因此,如果需要向体系结构中的其他层公开命令级属性,则必须使用上面讨论的分部类方法提供读取 Public 或写入 Private 命令对象的方法或属性。

总结

类型化数据集中的 TableAdapter 用于封装数据访问详细信息和复杂性。 使用 TableAdapters,我们不必担心编写 ADO.NET 代码以连接到数据库、发出命令或将结果填充到 DataTable 中。 这一切都会自动为我们处理。

但是,有时可能需要自定义低级别 ADO.NET 细节,例如更改连接字符串或默认连接或命令超时值。 TableAdapter 具有自动生成的 ConnectionAdapterCommandCollection 属性,但这些属性默认为 FriendPrivate。 可以通过使用分部类扩展 TableAdapter 以包含 Public 方法或属性来公开此内部信息。 或者,可以通过 TableAdapter s Connection 属性配置 TableAdapter 属性 ConnectionModifier 访问修饰符。

编程快乐!

关于作者

斯科特·米切尔是七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自 1998 年以来一直在使用 Microsoft Web 技术。 Scott 担任独立顾问、培训师和作家。 他的最新一本书是 山姆斯在 24 小时内 ASP.NET 2.0。 可以在 上mitchell@4GuysFromRolla.com联系他,也可以通过他的博客(可在 中找到http://ScottOnWriting.NET)。

特别感谢

本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 Burnadette Leigh、S ren Jacob Lauritsen、Teresa Murphy 和 Hilton Geisenow。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处mitchell@4GuysFromRolla.com放置一行。