Подтвердить что ты не робот

Как принудительно закрыть 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? (видимо, нет?)
  • Работает ли настройка "Max Pool Size = 0" в строке подключения? (это было бы пирровым решением)
  • Работает ли Dispose()?

Ссылки

4b9b3361

Ответ 2

Ответ Moe Sisko (Call SqlConnection.ClearPool) правильный.

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

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

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

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

Ответ 7

Роберт ответ SqlConnection.ClearPool(TheSqlConn) сделал именно то, что я хотел. Приятно знать, с каким пулом можно взаимодействовать, когда это необходимо.

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

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

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