Как принудительно физически закрыть SqlConnection при использовании пула соединений?

Я понимаю, что если я создаю экземпляр объекта 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 ответов

Решение

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

Ответ Мо Сиско (Позвони SqlConnection.ClearPool) верно.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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