Ответ 1
Оберните код обработки базы данных внутри "использования"
using (SqlConnection conn = new SqlConnection (...))
{
// Whatever happens in here, the connection is
// disposed of (closed) at the end.
}
Я использую шаблон, который часто выглядит примерно так. Мне интересно, все ли в порядке или есть лучшая практика, которую я здесь не применяю.
В частности, мне интересно; в случае, если выбрано исключение, есть код, который у меня есть в блоке finally, достаточный для обеспечения надлежащего закрытия соединения?
public class SomeDataClass : IDisposable
{
private SqlConnection _conn;
//constructors and methods
private DoSomethingWithTheSqlConnection()
{
//some code excluded for brevity
try
{
using (SqlCommand cmd = new SqlCommand(SqlQuery.CountSomething, _SqlConnection))
{
_SqlConnection.Open();
countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
}
}
finally
{
//is this the best way?
if (_SqlConnection.State == ConnectionState.Closed)
_SqlConnection.Close();
}
//some code excluded for brevity
}
public Dispose()
{
_conn.Dispose();
}
}
Оберните код обработки базы данных внутри "использования"
using (SqlConnection conn = new SqlConnection (...))
{
// Whatever happens in here, the connection is
// disposed of (closed) at the end.
}
.Net Framework поддерживает пул соединений по какой-либо причине. Доверяй это!:) Вам не нужно писать столько кода, чтобы подключиться к базе данных и освободить соединение.
Вы можете просто использовать оператор 'using' и будьте уверены, что 'IDBConnection.Release()' закроет соединение для вас.
Высокоразвитые "решения", как правило, приводят к ошибочному коду. Простой лучше.
Документы MSDN делают это довольно понятным...
Вероятно, у вас нет (и не хочу) отключить объединение пулов, поэтому пул в конечном итоге управляет состоянием соединения после вызова "Закрыть". Это может быть важно, поскольку вы можете быть смущены, глядя со стороны сервера базы данных на все открытые соединения.
Итак, зачем тестировать Closed? Просто вызовите Close().
Вот почему используемый блок приводит к закрытому соединению. используя вызовы Dispose для вас.
Важная подсказка. Спасибо, Эгон.
Я предполагаю, что с помощью "_SqlConnection.State == ConnectionState.Closed" вы имели в виду! =.
Это, безусловно, будет работать. Я думаю, что более привычно содержать сам объект соединения внутри оператора using, но то, что у вас есть, хорошо, если вы хотите по какой-то причине повторно использовать один и тот же объект подключения.
Одна вещь, которую вы обязательно должны изменить, это метод Dispose(). Вы не должны ссылаться на объект соединения в распоряжении, потому что он, возможно, уже был финализирован в этой точке. Вместо этого вы должны следовать рекомендуемому шаблону Dispose.
Так как вы все равно используете IDisposables. Вы можете использовать ключевое слово 'using', которое в основном эквивалентно вызову dispose в блоке finally, но выглядит лучше.
Поместите код закрытия соединения внутри блока "Наконец", как вы показываете. Наконец, блоки выполняются до того, как будет выбрано исключение. Использование блока "using" работает так же хорошо, но я нахожу явный метод "Наконец" более понятным.
Использование утверждений старой шляпы для многих разработчиков, но более молодые разработчики могут не знать об этом.
Смотрите этот вопрос для ответа:
Закрыть и удалить - что вызывать?
Если ваше время соединения является единственным вызовом метода, используйте функцию using
для языка, чтобы обеспечить правильную очистку соединения. Хотя блок try/finally
функционально одинаков, он требует большего количества кода, а ИМО менее читабельна. Нет необходимости проверять состояние соединения, вы можете вызвать Dispose
независимо от того, будет ли он работать с очисткой соединения.
Если срок службы вашего соединения соответствует времени жизни содержащего класса, тогда выполните IDisposable
и очистите соединение в Dispose
.
нет необходимости в попытке. Наконец, вокруг "использования", используя IS try..finally
Могу я предложить следующее:
class SqlOpener : IDisposable
{
SqlConnection _connection;
public SqlOpener(SqlConnection connection)
{
_connection = connection;
_connection.Open();
}
void IDisposable.Dispose()
{
_connection.Close();
}
}
public class SomeDataClass : IDisposable
{
private SqlConnection _conn;
//constructors and methods
private void DoSomethingWithTheSqlConnection()
{
//some code excluded for brevity
using (SqlCommand cmd = new SqlCommand("some sql query", _conn))
using(new SqlOpener(_conn))
{
int countOfSomething = Convert.ToInt32(cmd.ExecuteScalar());
}
//some code excluded for brevity
}
public void Dispose()
{
_conn.Dispose();
}
}
Надеюсь, что помогает:)