首页 > 解决方案 > 如何禁用 OLE DB 打开其他隐式非池连接?

问题描述

OLE DB 有一个鬼鬼祟祟的功能,如果您当前的连接很忙,它会默默地打开更多的数据库连接。

借助 SQL Server 2005 “本机客户端”,微软引入了一项功能,即一个连接可以支持多个活动记录集;这样您就可以通过单个连接正式激活多个记录集。但他们指出,启用它是一件棘手的事情,这就是为什么它自该功能的 beta 2 以来一直选择加入的原因。

秘密联系?真的吗?

Microsoft注意到此行为:

将 ADO 与 SQL Server Native Client 一起使用

在 OLE DB 提供程序的早期版本中,此代码将导致在第二次执行时创建隐式连接,因为每个连接只能打开一组活动的结果。因为隐式连接没有汇集在 OLE DB 连接池中,这将导致额外的开销。使用 SQL Server Native Client OLE DB 提供程序公开的 MARS 功能,您可以在一个连接上获得多个活动结果。

John C. Gordon [MSFT]在 Microsoft 论坛中 也提到了这一点:(存档

在 OLE DB 中,当活动结果集仍处于挂起状态时执行查询时,会产生一种称为“隐式连接”的东西。正如原始海报所指出的,这些对用户来说并不明显。我知道 SQLNCLI、SQLNCLI10 实现了这些,但我不记得 SQLOLEDB 是否实现了。然后发生的是服务器有 2 个连接,每个连接都有一个待处理的结果集。当您选择的许可模式是通过连接时,这是不愉快的。

MARS 公告博客条目 中也提到了这一点:(存档

将 MARS 与 SQL Native Client 一起使用 [Chris Lee]

第二个结果集每次打开时都使用新连接。这显然有一些开销(事实证明,额外的连接没有被池化,所以开销是每次完整的服务器连接网络协议交换)。这是 SQLOLEDB 和 SQL Native Client (OLE DB) 的默认行为——当主连接忙于默认结果集时,会生成一个新的隐式连接。

这是 OLE DB 内部的一项功能,旨在使数据访问更容易。

奖金喋喋不休

  • OLE DB 是一个低级、复杂的 API
  • ADO 是 OLE DB 的简化包装器

如何关闭它?

这种自动创建辅助连接显然不好。SQL Server ODBC 驱动程序没有这样做,这太糟糕了(因为它是 OLE DB 内部的一个功能,并且免费提供给 SQL Server 的 OLE DB 驱动程序。它不是 ODBC 内部的一个功能)。

我想确保我没有这样做。为此,我希望驱动程序在我不小心尝试执行此操作的代码中抛出错误。

如何关闭 OLE DB 隐式附加连接?

标签: oledboledbconnectionsql-server-mars

解决方案


解决方案是禁用 OLEDB 将在您背后打开多个连接的功能。

您可以将Multiple ConnectionsADO 连接的属性设置为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 驱动程序。(ADsDSO 对象)

事实上,他们查询ADsDSOObject (活动目录)提供程序的“ Multiple Connections”属性的行为会导致它抛出一个

“在集合中找不到项目”

稍后在运行SELECT 查询时出现异常。

甚至注释掉设置的代码:

prop.Value = false;

仍然会导致错误。

正是调用请求一个不存在的属性导致它失败的行为。这就是我们迭代属性的原因,并且只有在找到它时才设置它:OLEDB 驱动程序中的错误。


推荐阅读