|
楼主 |
发表于 2015-1-9 16:00
|
显示全部楼层
本帖最后由 liu-aguang 于 2015-1-9 19:54 编辑
一. 连接的重用与共享
在ADO出现之前,我们的应用程序是通过OLEDB去访问数据源的.OLEDB象积木,玩积木,不同的构建模块组合可以搭建功能各异的"作品"; OLEDB内部也有若干功能组件和服务. 应用程序调用不同组件或服务让它们协调工作即可访问不同的数据源,或实现不同的功能.
ADO是OLEDB的包装,简化了对OLEDB的使用.使用ADO访问数据源,不再需要一条条语句分别去调用若干功能组件或服务,而往往是通过设置对象属性或参数来达到调用各种组件或服务的目的. 所以讨论ADO,实际是在讨论OLEDB的运行机制.在OLEDB中有两个重要的概念:数据消费者和数据提供者.
数据消费者: 指想要得到数据源中的数据的程序或对象.如在VBA中使用ADO,可以认为VBA是数据消费者.
数据提供者: 也叫数据提供程序(Provider).它是ADO数据访问链条中直接与数据源打交道的部分.现在一般都由数据库生产商提供,如访问Microsoft Office数据源(Excel/Access/txt...)的数据提供者为:Microsoft Ace OLEDB.12.0. 不同类型的数据库往往其数据提供者是不同的.
用ADO(OLEDB)访问数据源有两种方式:一是在相关组件或服务的协作下直接向数据提供者要数据,由数据提供者去与数据源交互. 二是使用OLEDB提供的默认提供者(MSDASQL)调用ODBC数据源管理器,通过ODBC驱动程序与数据源交互. 上面的代码即是采用的第一种方式,如采用第二方式,其结论是一致的.本文在不特别提示时,讨论的是第一种方式.
当我们执行Connection.open语句的时候,从VBA的角度上看是创建一个链接实例. 而从内部运行机制来看,它是要求创建并打开一个到数据存储区(Data store)的连接. ADO中连接(Connection)对象有多个属性,其中有Provider和ConnectionString属性. 它们既可在OPEN前分别设置,也可以为一个整体作为Connection打开(Open)的参数. Provider属性值(如上面示例代码中的Microsoft Ace OLEDB.12.0),是连接中要使用的数据提供者,有了它就能创建一个连接.创建的过程是对相关组件和提供者初始化的过程,也是一个开销很大的过程.ConnectionString属性,是提供者与数据源交互,即打开连接的依据.
到这里有一个重要的概念,即重用和共享: OLEDB的组件或服务一当被调用或初始化,它是可以重用或共享的. 换句话说,创建一个连接,只要没有关闭它, 就可以被重用或共享. 在TEST2中,一个在循环体外的连接Conn1一当创建,循环体内的连接cnn使用的是同一个数据提供者,因此可以对它的重用和共享. 所以cnn.open并没有建立一个完整的连接. 从而大大节省了的运行的时间.
可见,创建与打开连接是两个不同的过程. 只不过被ADO整合在OPEN里了.假如我们把TEST2中循环外的连接Cnn1后面的数据库换为db2.mdb;而循环体内不改变,我们会得到一致的结论.
再看一个例子,附件中有若干不同的Excel工作簿,现在我们用重用的方式建立下面代码,对它们进行遍历:
- Sub Test5()
- tt = aa
- Dim cnn1 As New ADODB.Connection
- Dim cnn As ADODB.Connection
- myPath$ = ThisWorkbook.Path & ""
- myFile$ = Dir(myPath & "*.xls")
- cnn1.Open "Provider=Microsoft.Ace.OLEDB.12.0;Extended Properties=Excel 8.0;" & _
- "Data Source=" & myPath & "1111.xls" '这是一个不存在的工作簿.
- Do While myFile <> ""
- If myFile <> ThisWorkbook.Name Then
- Set cnn = New ADODB.Connection
- cnn.Open "Provider=Microsoft.Ace.OLEDB.12.0;Extended Properties=Excel 8.0;" & _
- "Data Source=" & myPath & myFile
- '.............
- cnn.Close
- Set cnn = Nothing
- End If
- myFile = Dir
- Loop
- cnn1.Close
- Set cnn1 = Nothing
- MsgBox aa - tt
- End Sub
-
复制代码 我们惊讶地发现,被重用的Cnn1连接,在它的ConnectionString属性中指定了一个并不在的工作簿, 奇怪的是连接同样成功建立,并且也达到了重用提效的结果.这里又涉及到另外一个问题:Connecton.open是打开一个到实际数据源的连接吗?
这个说法出现在很多资料,包括一些官方帮助里. 而在MSDN技术库中却是这样表述的:方法Open是--"Opens a connection to a data store."; 连接对象是--"A Connection object represents a physical connection to a data store". 他们使用的是数据存储区(Data
store),而非数据源(data source). 进而在基于OLEDB编程的论述中说到:当消费者向数据提供者请求一个数据源对象时,OLEDB的服务会从中拦截这一请求,并根据指定的提供者和连接属性返回给消费者一个代理数据源对象,而并不是一个实际的数据源对象.
由此,我们是否可以这样来认为:ADO中当执行OPEN命令时,首先激活相关组件和服务,并初始化,建立连接,然后根据字符串属性构建一个与实际数据源相匹配的数据存储区,数据存储区在物理上是一个具有某种结构的缓存区. 至于与实际数据源交互是其它对象或方法的事情(如execute).
不过,在打开连接时是否与实际数据源实现第一次握手,跟数据提供者有关,也和数据源类型有关. 比如,TEST5中,当数据源为Access时,就不能在连接字符中提供一个不存在的数据源.关于以上两点是笔者的猜测,不一定准确.
无论如何,从上面的分析中我们得到如下结论:
在需要频繁连接/断开的场境中,可以利用连接的重用和共享来提高效率. 它的编程技巧是: 定义并建立一个全局或模块级的可以重用的连接对象.
|
|