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

Когда я создаю временные таблицы, я получаю сообщение об ошибке о том, что временная таблица уже существует. Таблица temp уникальна для сеанса, поэтому кажется, что мое соединение не закрывается должным образом, и я думаю, что это может иметь какое-то отношение к оператору 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. Мне нужно вызвать connection.Close ()
  2. Мне нужно разместить оператор return за пределами моего оператора using
  3. Мне нужно удалить временную таблицу, которую я создал перед возвратом

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

Ответов (9)

Решение

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

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

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

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

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

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

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

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

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

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

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

Если не произойдет цикл включения питания или какой-либо другой серьезно причудливый угловой случай, БУДЕТ вызван.

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

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

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

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

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

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