Может ли оператор return помешать оператору using закрыть соединение с базой данных?

Когда я создаю временные таблицы, я получаю сообщение об ошибке, сообщающее, что временная таблица уже существует. Временная таблица является уникальной для сеанса, поэтому кажется, что мое соединение не закрывается должным образом, и я думаю, что это может иметь какое-то отношение к оператору return, который я имею в своем операторе using.

У меня есть следующий код:

using (IDbConnection connection = dbConnectionHandler.CreateConnection())
{
   connection.Open();
   CreateATempTable();
   PopulateTempTable();
   DataSet ds = CallStoredProcThatUsesTempTable();
   return ds;
}

Я использую этот вид кода в нескольких местах, чтобы создать временную таблицу с тем же именем.

К сожалению, я получаю следующую ошибку: There is already an object named '#MyTempTable' in the database,

Теперь я знаю, что временная таблица является уникальной для сеанса, поэтому после закрытия сеанса она должна исчезнуть.

Есть три вещи, которые я считаю, может вызвать это...

  1. Мне нужно вызвать соединение. Закрыть ()
  2. Мне нужно разместить оператор return за пределами моего оператора using
  3. Мне нужно удалить временную таблицу, которую я создал до возвращения

Кто-нибудь знает, какой это? или если это что-то, о чем я не думал?

9 ответов

Решение

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

Обычно при закрытии / удалении соединения на уровне библиотек.NET реальное соединение с сервером базы данных не закрывается. Он просто возвращается в пул соединений внутри провайдера данных и будет использоваться повторно, когда программа запросит другое соединение с теми же параметрами и учетными данными. Я не думаю, что сессия базы данных каким-либо образом сбрасывается перед возвратом в пул, за исключением открытых транзакций и, возможно, некоторых основных параметров. Более дорогие объекты, такие как временные таблицы, остаются одни.

Вы можете отключить объединение (очень неэффективно). Или вы можете проверить существование временной таблицы, прежде чем пытаться создать ее и удалить ее содержимое, если оно существует. Или вы можете удалить временную таблицу перед закрытием соединения.

Я почти уверен, что будет вызвано connection.Dispose() (и, следовательно, connection.Close()).

Вы можете легко это проверить, выполнив 1) и 2) и проверив, что проблема все еще существует. Решение, вероятно, 3), и объяснение будет пул соединений.

Блок с использованием преобразуется в блок try/catch/finally под капотом. Да, он будет распоряжаться независимо от возврата в блоке использования.

Если не произойдет энергетический цикл или не будет вызван какой-то другой причудливый случай, который можно утилизировать.

Если вы хотите доказательство, оберните объект и установите точку останова.

Нет, connection.Close всегда будет вызываться, потому что внутреннее использование помещает его в блок try/finally.

Вы также можете рассмотреть пул соединений. Попробуйте обернуть ваш код в TransactionScope.

Не зная больше об используемой библиотеке соединений с базой данных, я бы предположил, что это не один из первых двух; using был введен специально для облегчения очистки таких ресурсов при возврате из методов; это прямо аналогично обычному try...finally блок в Java или аналогичный.

Другими словами, return покинет блок и Dispose метод будет вызываться в соединении, которое должно, при условии разумной реализации такого, вызвать Close метод как часть этого процесса.

Ключевым моментом здесь является "вменяемая реализация".

Оператор using удалит объект, если его класс IDisposable, даже если в блоке using есть оператор return.

Это пул соединений, который поддерживает ваш #temptable, вы можете удалить эту таблицу вручную.

Это вызвано пулами соединений. Оберните то, что вы делаете в транзакции, и откатите ее в конце. Или удалите временную таблицу после заполнения ds.

Чтобы ответить на ваши вопросы:

  1. Оператор using неявно закрывает соединение, когда вызывается метод Dispose соединения.
  2. Это не должно быть необходимо: http://aspadvice.com/blogs/name/archive/2008/05/22/Return-Within-a-C_2300_-Using-Statement.aspx
  3. Попытайся.
Другие вопросы по тегам