如何禁止 OLE DB 打开额外的隐式非池化连接?

How to disable OLE DB from opening additional implicit non-pooled connections?

OLE DB 有一个偷偷摸摸的功能,如果您当前的连接繁忙,它会悄悄地打开更多的数据库连接。

在 SQL Server 2005 "native client" 中,Microsoft 引入了一项功能,其中一个连接可以支持 多个活动记录集;这样您就可以在 单个 连接上正式激活多个记录集。但他们注意到启用它是一件棘手的事情,这就是为什么自该功能的 beta 2 以来就选择加入的原因。

秘密联系?真的吗?

微软notes this behavior:

Using ADO with SQL Server Native Client

In prior versions of the OLE DB provider, this code would cause an implicit connection to be created on the second execution because only one active set of results could be opened per a single connection. Because the implicit connection was not pooled in the OLE DB connection pool this would cause additional overhead. With the MARS feature exposed by the SQL Server Native Client OLE DB provider, you get multiple active results on the one connection.

John C. Gordon [MSFT] 也注意到了它 in the Microsoft forums: (archive)

In OLE DB, there is something called an "implicit connection" spawned when a query is performed while an active resultset is still pending. These are not apparent to the user, as the original poster noticed. I know that SQLNCLI, SQLNCLI10 implement these, but it I do not remember if SQLOLEDB does. What then happens is the server has 2 connections and each one has one pending resultset. This is unpleasant when the licensing model you choose is by connection.

它也在 MARS announcement blog entry: (archive)

中注明

Using MARS with SQL Native Client [Chris Lee]

The second result set is using a new connection each time it is opened. This clearly has some overhead (and it turns out that the additional connections aren’t pooled, so the overhead is for a full server connection network protocol exchange each time). This is the default behavior for SQLOLEDB and SQL Native Client (OLE DB) – a new implicit connection is spawned when the main connection is busy with a default result set.

这是 OLE DB 中的一项功能,旨在简化数据访问。

Bonus Chatter

  • OLE DB is a low level, complicated, API
  • ADO is simplified wrapper around 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;
    }
}

请注意,关闭打开第二个连接的能力将意味着过去 看起来 正常工作的代码将突然开始 fail 并出现错误 “打开了一个对象”:

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(活动目录)提供程序导致它抛出一个

"Item could not be found in the collection"

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

甚至注释掉设置的代码:

prop.Value = false;

仍然会导致错误。

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