65.9K
CodeProject 正在变化。 阅读更多。
Home

在 .NET 中实现独立于提供程序的数据访问层

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.17/5 (42投票s)

2003年5月5日

6分钟阅读

viewsIcon

345818

downloadIcon

1426

本文介绍了如何实现一个独立于提供程序的数据访问层(DAL)。

引言

对于使用 Microsoft DNA 构建的应用程序,ADO 提供了一种最简单的数据访问方式。ADO 为开发人员提供了基于 COM 的数据访问 API,并且使用 ADO 组件可以访问多种数据源。这主要归因于 ADO 内部使用 OLEDB 提供程序连接数据源,更重要的是存在一个用于 ODBC 的 OLEDB 提供程序。这意味着开发人员也可以使用 ADO 通过连接字符串中的 DSN 连接 ODBC 源。

ADO.NET 中的数据访问方式并非完全相同。与只使用 OLEDB 的 ADO 不同,ADO.NET 提供了许多针对特定数据源的独立提供程序。例如,SQLClient 提供程序专门处理 SQL Server 7 和 SQL Server 2000 作为数据源。ODBC.NET 提供程序处理使用 ODBC 和 DSN 访问数据源。同样,OLEDB.NET 提供程序用于连接 OLEDB 数据源。此外,还存在一个独立的 .NET 提供程序用于 Oracle 数据库。

拥有独立的数据访问提供程序的好处是每个提供程序都针对特定的数据源进行了优化,并为该数据源提供最有效率的访问。例如,SQLClient 是迄今为止访问 SQL Server 7 或 2000 数据源最有效率的方式。但其缺点是开发人员可能需要决定使用特定的提供程序,而且通用的访问方式不像 ADO 那样简单。

那么,如果在应用程序运行时才决定选择提供程序呢?数据访问层(我们称之为 DAL)应该如何实现,才能让使用 DAL 的应用程序无需了解所使用的提供程序,并仍能与 DAL 无缝协作?本文将探讨 DAL 的设计和实现,以回答上述问题。

设计独立于提供程序的 DAL

编程独立于提供程序的 DAL 的关键是使用 System.Data 命名空间提供的一些接口,并且这些接口由所有提供程序实现。例如,有一个名为 IDbCommand 的接口,它表示要对数据源执行的 SQL 语句。像 SQLClient 和 OLEDB.NET 这样的提供程序,都在其各自的命令类中实现了此接口。下表显示了 DAL 中通常使用的接口。该表还给出了实现此接口的提供程序类

接口 SQLClient 类 ODBC.NET 类 OLEDB 类 描述
IDbConnection SqlConnection OdbcConnection OledbConnection 表示与数据库的连接
IDbDataAdapter SqlDataAdapter OdbcDataAdapter OleDbDataAdapter 表示一组用于处理 DataSet 的命令相关属性
IDbCommand SqlCommand OdbcCommand OleDbCommand 表示要对数据源执行的 SQL 语句(或命令)
IDataParameter SqlParameter OdbcParameter OleDbParameter 表示命令对象的参数
IDataReader SqlDataReader OdbcDataReader OleDbDataReader 表示一个或多个结果集,可以只读、只向前访问
IDbTransaction SqlTransaction OdbcTransaction OleDbTransaction 表示要对数据源执行的事务

注意:Oracle .NET 数据提供程序也实现了这些接口。

现在,让我们看一个简单的例子,了解如何使用这些接口

Private Function RunCommandReturnReader(ByRef Cmd As IDbCommand, 
                    ByRef conn As IDbConnection ) As IDataReader 
    Cmd.Connection = conn 
    Cmd.Connection.Open() 
    Return Cmd.ExecuteReader(CommandBehavior.CloseConnection) 
End Function

上面显示的是一个执行 Command 并返回 DataReader 对象的函数。请注意,该函数分别接受 IDbCommandIDbConnection 类型的两个参数,并返回 IDataReader 类型的对象。

上面显示的函数只是一个私有实用函数。在本文的后续部分,我将提供最终由 DAL 公开的函数的实现,该函数使用此实用函数返回 DataReader 对象。

Provider Factory

提供程序工厂是一个类,它公开了向调用者返回所需类型对象的方法。数据访问类使用提供程序工厂获取命令、连接对象等。数据访问类屏蔽了对象的实际类型。下面是 ProviderFactory 类的骨架

Imports Microsoft.Data.Odbc
Imports System.Data.SqlClient
Imports System.Data.OleDb
Imports System.Configuration

Public Class ProviderFactory
    Public Enum EnumProviders
        ODBC
        SQLClient
        OLEDB
    End Enum

    Public Shared Function GetConnection()
        As IDbConnection

        Select Case GetProvider()
        Case EnumProviders.ODBC
            Return New OdbcConnection()
        Case EnumProviders.SQLClient
            Return New SqlConnection()
        Case EnumProviders.OLEDB
            Return New OleDbConnection()

        End Select

    End Function 

    Public Shared Function GetProvider()
        As EnumProviders 

        Dim Idt As IDictionary = _           
          CType(ConfigurationSettings.GetConfig("AppProvider"), IDictionary)
        Return CType(Idt("Provider"), EnumProviders) 

    End Function 
End Class

上面显示的 ProviderFactory 类包含一个 EnumProviders 枚举,列出了支持的提供程序。在此示例中,支持三个提供程序:SQLClient、OLEDB.NET 和 ODBC.NET。还公开了一个 GetConnection 方法,该方法根据应用程序配置文件中的设置返回一个连接对象。如果开发人员将其设置为 0,则 GetConnection 返回一个 ODBCConnection 对象;如果设置为 2,则返回一个 OledbConnection 对象。在上面的示例中,我们实现了一个返回连接对象的方法。以类似的方式,提供程序工厂可以实现返回 CommandDataReaderDataAdapter 对象等的方法。

使用提供程序工厂

请注意,提供程序工厂负责返回正确类型的对象。因此,提供程序工厂的客户端只与接口一起工作。在下面显示的示例中,我们有一个执行命令并返回 DataReader 的函数。请注意,我们之前已经处理过辅助函数 RunCommandReturnReader

Public Function RunSQLReturnDataReader(ByVal strSQL As String,ByVal 
            cmdtype As CommandType) As IDataReader 
    Dim cmd As IDbCommand = ProviderFactory.GetCommand(strSQL, cmdtype) 
    Dim conn As IDbConnection = ProviderFactory.GetConnection("") 
    Return RunCommandReturnReader(cmd, conn) 
End Function

关于源代码

源代码 zip 文件包含一个 VB.NET 类库项目,其中包含简单的数据访问例程。这个助手可能无法满足企业应用程序 DAL 的所有需求,但它肯定说明了应用程序设计中类工厂模式的概念。

源代码的 V1.0 非常简单,没有做太多事情。这里的源代码是用框架的 v1.0 编译的,其中 ODBC.NET 提供程序是一个单独的下载。在框架的 v1.1 中,所有 ODBC 类现在都是 System.Data.ODBC 命名空间的一部分,该命名空间随框架一起发布。

许多读者想要一个使用 DAL 的示例应用程序。好吧,V2.0 源代码中有一个简单的应用程序,展示了 DAL 如何使用的几个实例。添加到 DAL 的许多功能包括

  • ADO.NET 事务支持
  • 参数缓存(基于数据访问应用程序块)
  • 参数发现(基于数据访问应用程序块)

最后两个对开发人员来说应该很有趣。在示例源代码中,我并没有真正利用参数缓存和发现。在实际应用程序中,这些对应用程序非常有用,可以提高应用程序的性能,同时减少编码工作量。例如,我们可以有一个 Windows 服务,托管一个定期发现和更新的参数缓存。这样,应用程序开发人员就不需要编写任何代码来构建参数集合,只需依赖服务即可。当然,您将需要一个远程基础设施与服务通信,但这也会非常高效。

致读者:源代码中的方法签名可能与本文文本中的略有不同。但是,概念仍然相同。

其他资源

我想推荐两个关于 .NET 中数据访问的优秀资源

结论

拥有独立于提供程序的 DAL 肯定能为应用程序提供更大的灵活性,可以在运行时选择正确的提供程序,并防止应用程序的其他部分锁定到特定的提供程序。

© . All rights reserved.