в блоке «using» есть SqlConnection, закрытое по возврату или исключению?

Первый вопрос:
Скажем, у меня есть

using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); string storedProc = "GetData"; SqlCommand command = new SqlCommand(storedProc, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); return (byte[])command.ExecuteScalar(); } 

Закрывается ли соединение? Потому что технически мы никогда не добираемся до последнего } пока мы return до него.

Второй вопрос:
На этот раз у меня есть:

 try { using (SqlConnection connection = new SqlConnection(connectionString)) { int employeeID = findEmployeeID(); connection.Open(); SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); command.CommandTimeout = 5; command.ExecuteNonQuery(); } } catch (Exception) { /*Handle error*/ } 

Теперь, скажем, где-то в try мы получаем ошибку, и она попадает. Закрыта ли связь? Потому что снова мы пропустим остальную часть кода в try и перейдем непосредственно к выписке.

Думаю ли я слишком линейно, как работает работа? т.е. Dispose() просто вызывается, когда мы покидаем область using ?

  1. да
  2. Да.

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

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

 using (SqlConnection connection = new SqlConnection(connectionString)) { int employeeID = findEmployeeID(); try { connection.Open(); SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); command.CommandTimeout = 5; command.ExecuteNonQuery(); } catch (Exception) { /*Handle error*/ } } 

Да на оба вопроса. Оператор using скомпилирован в блок try / finally

 using (SqlConnection connection = new SqlConnection(connectionString)) { } 

такой же как

 SqlConnection connection = null; try { connection = new SqlConnection(connectionString); } finally { if(connection != null) ((IDisposable)connection).Dispose(); } 

Изменить: привязка приведения к одноразовому http://msdn.microsoft.com/en-us/library/yh598w02.aspx

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

 string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CompanyServer"].ConnectionString; string selectStatement = @" SELECT TOP 1 Person FROM CorporateOffice WHERE HeadUpAss = 1 AND Title LIKE 'C-Level%' ORDER BY IntelligenceQuotient DESC "; using (SqlConnection conn = new SqlConnection(connString)) { using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) { if (dr.HasRows) { while (dr.Read()) { Console.WriteLine(dr["Person"].ToString()); } } else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); } } - string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CompanyServer"].ConnectionString; string selectStatement = @" SELECT TOP 1 Person FROM CorporateOffice WHERE HeadUpAss = 1 AND Title LIKE 'C-Level%' ORDER BY IntelligenceQuotient DESC "; using (SqlConnection conn = new SqlConnection(connString)) { using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) { if (dr.HasRows) { while (dr.Read()) { Console.WriteLine(dr["Person"].ToString()); } } else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); } } 

* Пересмотренный: 2015-11-09 *
Как было предложено NickG; Если слишком много брекетов раздражает вас, отформатируйте вот так …

 using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); } 

Опять же, если вы работаете в играх EA или DayBreak, вы можете просто отказаться от любых перерывов, потому что они предназначены только для людей, которые должны вернуться и посмотреть на свой код позже и кто действительно заботится? Я прав? Я имею в виду 1 строку вместо 23 означает, что я лучший программист, не так ли?

 using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); } 

Фу … Хорошо. Я получил это из своей системы и немного занят собой. Продолжать.

Dispose просто вызывается, когда вы покидаете область использования. objective «использования» – предоставить разработчикам гарантированный способ убедиться в том, что ресурсы будут утилизированы.

Из MSDN :

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

Using генерирует try / finally вокруг выделенного объекта и вызывает Dispose() для вас.

Это избавляет вас от необходимости вручную создавать блок try / finally и вызывать Dispose()

В вашем первом примере компилятор C # фактически преобразует оператор using в следующее:

 SqlConnection connection = new SqlConnection(connectionString)); try { connection.Open(); string storedProc = "GetData"; SqlCommand command = new SqlCommand(storedProc, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); return (byte[])command.ExecuteScalar(); } finally { connection.Dispose(); } 

Наконец, операторы всегда вызывают вызов до возвращения функции, и поэтому соединение всегда будет закрыто / удалено.

Итак, во втором примере код будет скомпилирован следующим образом:

 try { try { connection.Open(); string storedProc = "GetData"; SqlCommand command = new SqlCommand(storedProc, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID)); return (byte[])command.ExecuteScalar(); } finally { connection.Dispose(); } } catch (Exception) { } 

Исключение будет обнаружено в заявлении finally и соединение закрыто. Исключение не будет видно из предложения внешнего catch.

Я написал два оператора using внутри блока try / catch, и я видел, что исключение было поймано таким же образом, если оно помещено во внутренний оператор using так же, как пример ShaneLS.

  try { using (var con = new SqlConnection(@"Data Source=...")) { var cad = "INSERT INTO table VALUES (@r1,@r2,@r3)"; using (var insertCommand = new SqlCommand(cad, con)) { insertCommand.Parameters.AddWithValue("@r1", atxt); insertCommand.Parameters.AddWithValue("@r2", btxt); insertCommand.Parameters.AddWithValue("@r3", ctxt); con.Open(); insertCommand.ExecuteNonQuery(); } } } catch (Exception ex) { MessageBox.Show("Error: " + ex.Message, "UsingTest", MessageBoxButtons.OK, MessageBoxIcon.Error); } 

Независимо от того, где находится try / catch , исключение будет устранено без проблем.

Interesting Posts

Как напечатать f «unsigned long» в C?

Как получить элементы управления в WPF для заполнения свободного пространства?

Остановите запущенный процесс запуска на OS X Leopard

Переместите пользовательский каталог Windows 7 в D: \ user

Сравните равенство между двумя объектами в NUnit

javax.crypto.BadPaddingException

HTTP POST возвращает ошибку: 417 «Ожидание не выполнено».

Многомерный массив vs

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

Как наилучшим образом реализовать Equals для пользовательских типов?

Высокая производительность ATI Radeon HD 4650 в режиме работы от батареи

Почему мое соединение ODBC не работает при запуске нагрузки SSIS в Visual Studio, но не при запуске одного и того же пакета с помощью утилиты Execute Package Utility

Настройки отправки электронной почты с localhost для PHP-кода в Windows Vista

Win-Tab не работает

Динамические столбцы с поворотным контуром, без агрегации

Давайте будем гением компьютера.