Использование (var connection = new SqlConnection("ConnectionString")) все еще закрывает / удаляет соединение при ошибке?
У меня есть следующий код
try
{
using (var connection = new SqlConnection(Utils.ConnectionString))
{
connection.Open();
using (var cmd = new SqlCommand("StoredProcedure", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var sqlParam = new SqlParameter("id_document", idDocument);
cmd.Parameters.Add(sqlParam);
int result = cmd.ExecuteNonQuery();
if (result != -1)
return "something";
//do something here
return "something else";
}
}
//do something
}
catch (SqlException ex)
{
return "something AKA didn't work";
}
Вопрос в том: var connection
по-прежнему закрыты, если между using
скобки ({ }
)?
Проблема в том, что большинство моих вызовов хранимых процедур выполняются таким образом, и недавно я получил эту ошибку:
System.InvalidOperationException: истекло время ожидания. Период ожидания истек до получения соединения из пула. Это могло произойти из-за того, что все пул соединений использовались и был достигнут максимальный размер пула.
Другой способ доступа к БД - через nHibernate.
5 ответов
используя Statement (C# Reference)
Оператор using гарантирует, что Dispose вызывается, даже если возникает исключение, когда вы вызываете методы объекта. Вы можете достичь того же результата, поместив объект в блок try, а затем вызвав Dispose в блоке finally; на самом деле, именно так оператор using переводится компилятором. Ранее приведенный пример кода расширяется до следующего кода во время компиляции (обратите внимание на дополнительные фигурные скобки, чтобы создать ограниченную область видимости для объекта):
Да, если он попадает в тело using
оператор, он будет расположен в конце... независимо от того, достигли ли вы конца блока нормально, завершились оператором return или было сгенерировано исключение. В основном using
утверждение эквивалентно try
/finally
блок.
Это единственное место, где вы приобретаете связь? Возможно, ваша хранимая процедура где-то заблокирована, оставляя множество подключений действительно "занятыми" в отношении клиентского кода?
С точки зрения того, что в вашем пуле соединений заканчиваются доступные соединения, если вы находитесь в распределенной среде и используете много приложений для доступа к SQL Server, но все они используют одну и ту же строку соединения, то все они будут использовать один и тот же пул на сервере. Чтобы обойти это, вы можете изменить строку подключения для каждого приложения, установив для идентификатора соединения Workstation значение Environment.MachineName. Это заставит сервер видеть каждое соединение как отдельное и предоставлять пул для каждой машины вместо совместного использования пула.
В приведенном ниже примере мы даже передаем токен, чтобы приложение на одном компьютере могло иметь несколько пулов.
Пример:
private string GetConnectionStringWithWorkStationId(string connectionString, string connectionPoolToken)
{
if (string.IsNullOrEmpty(machineName)) machineName = Environment.MachineName;
SqlConnectionStringBuilder cnbdlr;
try
{
cnbdlr = new SqlConnectionStringBuilder(connectionString);
}
catch
{
throw new ArgumentException("connection string was an invalid format");
}
cnbdlr.WorkstationID = machineName + connectionPoolToken;
return cnbdlr.ConnectionString;
}
Замените свой код выше.. этим.. и проверьте еще раз..
try
{
using (var connection = new SqlConnection(Utils.ConnectionString))
{
connection.Open();
using (var cmd = new SqlCommand("StoredProcedure", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
var sqlParam = new SqlParameter("id_document", idDocument);
cmd.Parameters.Add(sqlParam);
int result = cmd.ExecuteNonQuery();
if (result != -1)
return "something";
//do something here
return "something else";
}
connection.Close();
connection.Dispose();
}
//do something
}
catch (SqlException ex)
{
return "something AKA didn't work";
}
Вот ссылка:
http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
Что я знаю, так это то, что если вы используете объект в предложении using {}, этот объект наследует интерфейс IDisposable (то есть SqlConnection наследует DbConnection, а DbConnection наследует IDisposable), что означает, что если вы получите исключение, любой объект будет закрыт и удален должным образом.