Может ли оператор return помешать оператору using закрыть соединение с базой данных? - PullRequest
4 голосов
/ 26 февраля 2009

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

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

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 ]

6 голосов
/ 26 февраля 2009

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

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

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

3 голосов
/ 26 февраля 2009

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

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

1 голос
/ 26 февраля 2009

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

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

1 голос
/ 26 февраля 2009

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

1 голос
/ 26 февраля 2009

Если не произойдет выключение питания или не будет вызвано какое-либо другое странное решение по делу о углу,

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

0 голосов
/ 26 февраля 2009

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

0 голосов
/ 26 февраля 2009

с использованием оператора будет уничтожать объект, если его класс IDisposable, даже если в блоке использования есть оператор возврата.

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

0 голосов
/ 26 февраля 2009

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

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

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

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

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

...