OLE DB有一个偷偷摸摸的功能,如果你当前的连接繁忙,它将静默地打开更多的数据库连接。
- 这些发生在您不知情的情况下
- 并且它们不会从连接池中取出或返回到连接池
在SQL Server 2005">本机客户端">中,Microsoft引入了一个连接可以支持多个活动记录集的功能;因此,您可以通过单个连接正式激活多个记录集。但他们指出,启用这是一件棘手的事情,这就是为什么自该功能的测试版 2 以来一直选择加入的原因。
秘密联系?真?
Microsoft注意此行为:
将 ADO 与 SQL Server 本机客户端配合使用
在早期版本的 OLE DB 提供程序中,此代码将导致在第二次执行时创建隐式连接,因为每个连接只能打开一组活动结果。由于隐式连接未在 OLE DB 连接池中池化,因此会导致额外的开销。使用 SQL Server 本机客户端 OLE DB 提供程序公开的 MARS 功能,您可以在一个连接上获得多个活动结果。
John C. Gordon[MSFT]在Microsoft论坛中也注意到了这一点:(存档(
在 OLE DB 中,在活动结果集仍处于挂起状态时执行查询时,会生成一种称为"隐式连接"的东西。 正如原始海报所注意到的那样,这些对用户来说并不明显。 我知道 SQLNCLI SQLNCLI10实现这些,但我不记得 SQLOLEDB 是否实现了这些。 然后发生的情况是服务器有 2 个连接,每个连接都有一个挂起的结果集。 当您选择的许可模式是通过连接时,这是令人不快的。
在MARS公告博客条目中也指出:(存档(
将 MARS 与 SQL Native Client 结合使用 [Chris Lee]
第二个结果集在每次打开时都使用新连接。这显然有一些开销(事实证明,额外的连接没有池化,因此开销是每次进行完整的服务器连接网络协议交换(。这是 SQLOLEDB 和 SQL 本机客户端 (OLE DB( 的默认行为 – 当主连接忙于默认结果集时,将生成新的隐式连接。
这是 OLE DB 内部的一项功能,旨在简化数据访问。
奖金喋喋不休
- OLE DB 是一个低级、复杂的 API
- ADO 是围绕 OLE DB 的简化包装器
如何关闭它?
这种自动创建辅助连接显然不好。SQL Server ODBC驱动程序不这样做太不好了(因为它是OLE DB深处的一项功能,并且免费提供给SQL Server的OLE DB驱动程序。它不是 ODBC 中的功能(。
我想确保我没有这样做。为此,我希望驱动程序在我的代码中意外尝试执行此操作的位置抛出错误。
如何关闭 OLE DB 隐式附加连接?
解决方案是禁用 OLEDB 将在您背后打开多个连接的功能。
可以将 ADO 连接的Multiple Connections
属性设置为false
,以防止它在主连接忙于结果集时隐式打开第二个连接。
//Set Connection.Properties["Multiple Connections"] = false
for int i = 0 to Connection.Properties.Count-1
{
Property prop = Connection.Properties.Item[i];
if (prop.Name == "Multiple Connections")
{
prop.Value = false;
break;
}
}
请注意,关闭打开第二个连接的功能将意味着过去看似有效的代码将突然开始失败,并显示错误"对象已打开">:
OleDbErr.h
//
// MessageId: DB_E_OBJECTOPEN
//
// MessageText:
//
// An object was open
//
#define DB_E_OBJECTOPEN ((HRESULT)0x80040E05L)
警告
Multiple Connections
属性不适用于 ODBC OLEDB 驱动程序 (MSDASQL( 或 Active Directory 驱动程序。(ADsDSOObject(
事实上,他们非常查询"Multiple Connections
" 属性的行为ADsDSOObject(活动目录(提供程序导致它抛出一个
"在集合中找不到项目">
稍后运行SELECT 查询时出现异常。
甚至注释掉设置的代码:
prop.Value = false;
仍然导致错误。
正是调用请求不存在的属性的行为导致它失败。这就是为什么我们迭代属性,并且只有在找到它时才设置它:OLEDB 驱动程序中的错误。