Как принудительно физически закрыть SqlConnection при использовании пула соединений? - PullRequest
37 голосов
/ 18 июля 2009

Я понимаю, что если я создаю экземпляр объекта SqlConnection, я действительно получаю соединение из пула соединений. Когда я вызываю Open (), он открывает соединение. Если я вызываю метод Close () или Dispose () для этого объекта SqlConnection, он возвращается в пул соединений.

Однако, это не говорит мне, действительно ли оно закрыто или у меня все еще есть активное соединение с базой данных.

Как заставить SqlConnection закрыться на сетевом уровне или хотя бы сказать, когда он закрывается?

Пример:

using(SqlConnection conn = new SqlConnection(DBConnString)) {

   conn.Open();
   SqlCommand cmd = conn.CreateCommand();
   ...
   cmd.ExecuteReader(CommandBehavior.CloseConnection);
   ...
}
  • Первый запуск: 300 мс
  • Второй запуск: 100 мс
  • Третий прогон: 100 мс
  • После долгого ожидания (30 минут): 300 мс

Если соединение было TRULY закрыто, второй и третий прогоны также должны составлять 300 мс. Но я знаю, что для этих запусков соединение по-настоящему не закрыто (я проверил монитор активности SQL Server). Для аутентификации / т. Д. Не требуется дополнительных 200 мс.

Как заставить соединение действительно закрыться?

Идеи

  • Работает ли CommandBehavior.CloseConnection? (видимо нет?)
  • Работает ли настройка "Максимальный размер пула = 0" в строке подключения? (это было бы пирровым решением)
  • Работает ли Dispose ()?

Ссылки

Ответы [ 7 ]

51 голосов
/ 18 июля 2009

Может быть SqlConnection.ClearPool?

24 голосов
/ 03 февраля 2010

Ответ Мо Сиско (Зов SqlConnection.ClearPool) правильный.

Иногда вам нужно соединение, чтобы действительно закрыть, а не вернуться в пул. Например, у меня есть модульный тест, который создает чистую базу данных, строит схему, проверяет некоторые вещи, а затем удаляет чистую базу данных, если все тесты пройдены.

Когда пул соединений активен, команда сброса базы данных не выполняется, поскольку все еще существуют активные соединения. С точки зрения программиста, все SQLConnections закрыты, но, поскольку пул все еще держит один открытый, SQL Server не допустит удаления.

Лучшая документация о том, как обрабатывается пул соединений, - эта страница о пуле соединений SQL Server в MSDN. Никто не хочет полностью отключать пул соединений, потому что это улучшает производительность при многократных открытиях и закрытиях, но иногда вам нужно вызвать «принудительное закрытие» для SQLConnection, чтобы он освободил базу данных.

Это делается с помощью ClearPool. Если вы позвоните SqlConnection.ClearPool(connection) до закрытия / утилизации, когда вы действительно закроете / утилизируете, он действительно исчезнет.

9 голосов
/ 18 июля 2009

Если вы не хотите использовать пул соединений, вы должны указать его в свойстве SqlConnection.ConnectionString. Например

"Data Source=MSSQL1;Database=AdventureWorks;Integrated Security=true;Pooling=false;"

Удаление или закрытие объекта SqlConnection просто закрывает соединение и возвращает его в пул соединений.

3 голосов
/ 18 июля 2009

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

Почему именно вы не хотите, чтобы соединение не возвращалось в пул?

0 голосов
/ 28 января 2019

Я вижу, что вы используете .net, но, как это выяснилось в запросе Google, позвольте мне дать ответ Java ...

Используйте DataSource, который реализует Closeable (), и вызывайте close для DataSource. Hikari поддерживает Closeable.

0 голосов
/ 01 ноября 2016

Ответ Роберта SqlConnection.ClearPool(TheSqlConn) сделал именно то, что я хотел. Приятно знать, что пул МОЖЕТ взаимодействовать при необходимости.

Мой пример использования: мы испортили соединение и позволили ему вернуться в пул, как определить, что оно испорчено, и обновить его, чтобы у следующего пользователя не возникло проблем.

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

Десять лет написания SqlClient.SqlConnection, и я даже не думал о взаимодействии с пулом до сегодняшнего дня.

0 голосов
/ 18 июля 2009

CommandBehavior.CloseConnection обычно не рекомендуется из-за этого самого факта - Вы не можете быть уверены, что Соединение будет закрыто. (Я попытаюсь найти какое-то конкретное подтверждение этому, я говорю это по слабому воспоминанию).

Dispose() является верным способом, потому что он неявно вызывает Close().

Конструкция using, продемонстрированная @Alex, является еще одним (дружественным для программиста) способом написания конструкции try-finally с добавлением неявного удаления объектов.

Редактировать: (после редактирования вопроса)

Ваша обеспокоенность связями на самом деле закрытие кажется мне неоправданным. Соединение просто вернется в пул, чтобы его можно было легко использовать повторно, не выполняя всю инициализацию. Это не означает, что Соединение все еще активно подключено к БД.

...