Как отключить OLE DB от открытия дополнительных неявных соединений без пула?

OLE DB имеет скрытую функцию, при которой, если ваше текущее соединение занято, оно будет молча открывать больше соединений с базой данных.

  • это происходит без вашего ведома
  • и они не взяты или не возвращены в пул соединений

В SQL Server 2005 "собственный клиент" Microsoft представила функцию, в которой одно соединение может поддерживать несколько активных наборов записей; так что вы можете официально иметь несколько активных наборов записей по одному соединению. Но они отмечают, что включить его сложно, поэтому он включен с бета-версии 2 функции.

Секретные связи? В самом деле?

Microsoft отмечает это поведение:

Использование ADO с собственным клиентом SQL Server

В предыдущих версиях поставщика OLE DB этот код приводил к созданию неявного соединения при втором выполнении, поскольку на одно соединение можно было открыть только один активный набор результатов. Поскольку неявное соединение не было помещено в пул соединений OLE DB, это может привести к дополнительным издержкам. С помощью функции MARS, предоставляемой поставщиком OLE DB для собственного клиента SQL Server, вы получаете несколько активных результатов для одного подключения.

Это также отметил Джон С. Гордон [MSFT] на форумах Microsoft:( архив)

В OLE DB есть нечто, называемое "неявное соединение", порождаемое, когда запрос выполняется, пока активный набор результатов еще не завершен. Они не очевидны для пользователя, как заметил оригинальный постер. Я знаю, что SQLNCLI, SQLNCLI10 реализуют их, но я не помню, если SQLOLEDB делает. Затем происходит то, что сервер имеет 2 соединения, и у каждого есть один ожидающий результат. Это неприятно, когда вы выбираете модель лицензирования по соединению.

Это также отмечено в записи в блоге MARS:( архив)

Использование MARS с собственным клиентом SQL [Chris Lee]

Второй набор результатов использует новое соединение каждый раз, когда оно открывается. Это явно имеет некоторые издержки (и оказывается, что дополнительные соединения не объединяются в пул, поэтому накладные расходы каждый раз связаны с полным обменом сетевым протоколом соединений с сервером). Это поведение по умолчанию для SQLOLEDB и собственного клиента SQL (OLE DB) - новое неявное соединение создается, когда основное соединение занято набором результатов по умолчанию.

Это функция глубоко внутри OLE DB, предназначенная для облегчения доступа к данным.

Бонус Болтовня

  • OLE DB - это сложный API-интерфейс низкого уровня
  • ADO - упрощенная обёртка вокруг OLE DB

Как его выключить?

Это автоматическое создание вторичных соединений, очевидно, не хорошо. Не очень хорошо, что драйвер ODBC для SQL Server этого не делает (потому что это функция глубоко внутри OLE DB и поставляется бесплатно с драйверами OLE DB для SQL Server. Это не функция внутри ODBC).

Я хочу убедиться, что я не делаю это. Для этого я хочу, чтобы драйвер выдавал ошибку в том месте моего кода, где я случайно попытался это сделать.

Как отключить неявные дополнительные подключения OLE DB?

1 ответ

Решение

Решение состоит в том, чтобы отключить функцию, при которой OLEB будет открывать несколько подключений за вашей спиной.

Вы можете установить свойство вашего ADO Connection на false чтобы предотвратить неявное открытие 2-х соединений, когда основное соединение занято набором результатов.

      //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)

Предупреждение

Это свойство не применяется к драйверу ODBC OLEDB (MSDASQL) или драйверу Active Directory. (ADsDSOObject)

Фактически, они очень активно запрашивают " Multiple Connections"свойство поставщика ADsDSOObject (активный каталог) заставляет его генерировать

«Товар не найден в коллекции»

исключение позже при выполнении запроса SELECT.

Даже комментируя код, который устанавливает:

      prop.Value = false;

по-прежнему вызывает ошибку.

Сам акт вызова с просьбой о несуществующем свойстве приводит к его отказу. Вот почему мы перебираем свойства и устанавливаем их только в том случае, если обнаруживаем: ошибки в драйверах OLEDB.

Другие вопросы по тегам