Почему одна публичная OleDbConnection устарела?Альтернатива для устранения ошибки: слишком много соединений открыто - PullRequest
6 голосов
/ 15 июня 2011

Я должен работать с Проектом, сделанным другим разработчиком.Win-Form проекта с кодом Visual-Basic, с MS-Access как db и некоторыми OleDbConnections.Есть ошибка: иногда приложение не может открыть OleDbConnection, потому что максимальное количество соединений было достигнуто на БД.Я знаю, что лучший способ использовать соединения таков:

Using cn As New OleDbConnction(s)
  ...
  cn.Close()
End Using

Но в проекте есть много классов для работы с БД, и во многих из этих классов есть OleDbConnections с видимостью "Друг",которые открываются и закрываются в разное время.По этой причине невозможно поместить все OleDbConnections в конструкцию Using, и очень очень трудно найти, какая операция «забывает» закрыть одну из этих OleDbConnection.

Возможным решением может быть использование только одного уникальногоpublic OleDbConnection, и проверить, прежде чем открывать его, если он еще не открыт.Но кто-то сказал мне, что это очень плохая практика.Полагаю, он рассказал мне об этом спектакле, но я точно не знаю.Можете ли вы сказать мне, почему один уникальный публичный OleDbConnection так устарел?Вы нашли для меня «простое» решение моей проблемы?Спасибо, Пиледжи

Ответы [ 2 ]

6 голосов
/ 16 июня 2011

Из вашего описания я вижу несколько возможных проблем, которые могут привести к вашей проблеме:

  • вложенные соединения:
    Вы открываете несколько соединений друг с другом
  • слишком быстрое открытие / разблокирование соединений:
    Как отметил Дэвид-В-Фентон, при доступе каждый раз, когда вы открываете / закрываете одно соединение, файл блокировки будет создаваться / удаляться. Эта операция довольно медленная, и если вы быстро открываете / закрываете базу данных в своем приложении (выполняете много атомарных запросов), вы можете получить эту проблему.

Несколько возможных способов исследования и решения проблемы:

Отслеживание всех открытых / закрытых вызовов
Добавьте несколько трасс отладки, которые отображаются при каждом открытии и закрытии соединения.
Это позволит вам обнаружить вложенные соединения и определить, где ваш пул соединений теряется.

Опрос силового соединения Простое «исправление» может заключаться в том, чтобы явно установить пул соединений в строке соединения. Это должно быть поведение по умолчанию, поэтому, возможно, оно ничего не изменит для решения вашей проблемы, но это настолько просто, что нет причин не пытаться это делать:

OLE DB Services=-1

Используйте класс диспетчера подключений , чтобы создавать / освобождать подключения для вас.
Замените все явные создания новых операций OleDbConnection и close на ваш собственный код. Это позволит вам всегда повторно использовать одно существующее соединение во всем приложении и позволит вам быстро настроить все приложение, централизовав его поведение в одном месте.

Так почему удерживать одно соединение вообще не рекомендуется?

  • Как правило, вам не следует оставлять соединения открытыми во всем приложении, так как они заставляют сервер базы данных сохранять ресурсы доступными для вас, и это уменьшает количество клиентов, которые могут подключаться (всегда доступно ограниченное количество подключений). ).
    Для Access, хотя - файловая база данных без серверной части - сохранение единственного открытого соединения на самом деле предпочтительнее из-за задержки, связанной с открытием новых соединений (создание файла блокировки). Так как Access не предназначен для использования с большим количеством одновременно работающих пользователей, стоимость ресурсов для поддержания открытого соединения недостаточно велика, чтобы быть проблемой.
    Из простых тестов можно показать, что поддержание соединения всегда открытым позволяет последующим соединениям открываться примерно в 10 раз быстрее!

  • Драйвер OleDb выполняет пул соединений для вас, поэтому он может повторно использовать соединения после их освобождения.

  • Если ваши соединения и операции с базой данных будут небольшими и ограниченными, вы вряд ли столкнетесь с проблемами параллелизма при использовании потоков. Сохранение глобального соединения может стать проблемой, если вы выполняете несколько операций, используя один и тот же конвейер для базы данных.

2 голосов
/ 08 августа 2014

Просто добавив некоторую информацию, которая успешно работает для меня годами (это несколько похоже на то, что Дэвид-В-Фентон предлагает )

Во-первых, OleDbConnection для Microsoft Access (MDB, JET) не с использованием пула соединений.Как Microsoft заявляет в KB191572 :

Соединения, в которых используются поставщики Jet OLE DB и драйверы ODBC, не объединяются в пул, поскольку эти поставщики и драйверы не поддерживают пул.

Что касается пула соединений, существует также это сообщение в блоге от Ивана Митева , в котором говорится:

Так что это значит?Очевидно, что наличие активно открытого соединения сделало тест с многократным закрытием и открытием соединения намного быстрее (в 2-3 раза).Единственное возможное объяснение для меня - то, что пул соединений освобождается каждый раз, когда нет активных соединений.Я должен провести дальнейшие исследования и прочитать что-то вроде пула в компонентах доступа к данным Microsoft.Или, может быть, удерживать одно открытое соединение только для того, чтобы пул оставался в живых.Это было бы некрасиво, но все же это достаточно хороший обходной путь!Если у кого-то есть идея получше, поделитесь ею.

И заметки Microsoft в MSDN :

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

На основании всего этого и моих собственных тестов мое решение для "имитации" пула соединенийдаже с базами данных Microsoft Access примерно выполняет следующие действия:

  1. Откройте одну OleDbConnection для базы данных Access как можно раньше в жизненном цикле приложения.
  2. Выполняйте обычные запросы SQL, располагая OleDbConnection с как можно раньше, как рекомендовано.
  3. Утилизируйте один всегда открытый OleDbConnection как можно позже в жизненном цикле приложения.

Это ускорило мои приложения (в основном это WinForms).

Обратите внимание, что это также работает для Sqlite, который, похоже, также не поддерживает пул соединений.

...