С# - закрытие лучших объектов Sql
Если у вас есть функция С# с Sqlaccess, обязательно закрыть все объекты/дескрипторы или все очистится автоматически после выхода из функции
Например:
void DoSqlStuff()
{
SqlConnection sqlConn = new SqlConnection(...);
SqlCommand cmd = new SqlCommand(...);
SqlDataReader sqlData= null;
sqlConn,Open();
sqlData = cmd.ExecutReader();
while(sqlData.Read())
{
...
}
}
Необязательно, рекомендуется или обязательно закрыть SqlConn и SqlData?
Спасибо.
Ответы
Ответ 1
Вы должны закрыть объект SqlConnection, как только закончите с ним. Если вы этого не сделаете, соединение останется открытым и не будет доступно для обработки других запросов.
Оператор using полезен для этого. Он вызовет Dispose() для объекта для вас:
using (SqlConnection cn = new SqlConnection(connectionString))
{
SqlCommand cm = new SqlCommand(commandString, cn)
cn.Open();
cm.ExecuteNonQuery();
}
Ответ 2
Вам не нужно иметь отдельный оператор using для SqlDataReader (а также один оператор using для соединения), если вы не планируете выполнять другие операции с соединением после того, как SqlDataReader полностью прочитал набор строк.
Если вы только открываете соединение, читая некоторые данные с помощью читателя, а затем закрывая соединение, то один оператор using для всего блока кода (окружающего соединение) будет достаточным, поскольку сборщик мусора очистит все ресурсы привязанного к соединению, которое расположено с помощью первого оператора using.
В любом случае, здесь хорошая статья которая описывает все это...
Ответ 3
Вы должны закрыть все перед возвратом из функции. Открытые datareaders означают открытые курсоры в базе данных, что приводит к увеличению использования памяти. То же самое касается соединений с базой данных.
Неиспользуемые объекты не сразу освобождаются на С#, но только тогда, когда выполняется сбор мусора, который не является детерминированным.
Ответ 4
Все три класса имеют метод Dispose(). Обязательный слишком сильный, но определенно рекомендуется использовать ключевое слово using, поэтому Dispose() автоматически вызывается. В противном случае ваша программа будет работать "тяжело", используя больше системных ресурсов, чем это необходимо. И прямой сбой, когда вы не используете "новое" ключевое слово, чтобы вызвать сборщик мусора.
Ответ 5
Вызов Close на SQL-соединении фактически не закрывает его, а возвращает его в пул соединений, который будет использоваться повторно, и улучшая производительность.
Кроме того, как правило, плохой практикой не явным образом распоряжаться неуправляемыми ресурсами, когда вы закончите с ними (asap).
Ответ 6
Явное распоряжение в заявлении finally - это еще один подход, хотя утверждение using
является гораздо лучшим решением. Он создает немного больше кода, но демонстрирует цель...
SqlConnection conn = null;
try
{
//create connection
SqlCommand cmd = null;
try
{
//create command
SqlDataReader reader = null;
try
{
//create reader
}
finally
{
reader.Dispose();
}
}
finally
{
cmd.Dispose();
}
}
finally
{
conn.Dispose();
}
Ответ 7
Будьте осторожны с абсолютами здесь. Многое зависит от того, что вы делаете и где могут быть неэффективны.
На веб-странице, где каждый пользователь имеет отдельный контекст безопасности, у вас может не быть другого выбора, кроме как установить новое соединение SQL с новыми учетными данными безопасности с каждым ударом страницы. Ясно, если вы можете использовать пул соединений SQL с общим контекстом безопасности и позволить веб-странице фильтровать результаты, но, возможно, вы не можете.
В ранних версиях SQL Server, т.е. (v6.5 или менее), аутентификация входа выполнялась SQL Server. Кроме того, SQL был сильно ограничен памятью подключения и количеством активных подключений, которые он мог бы обрабатывать. Поэтому было прекрасной идеей отказаться от вашей связи, когда она не используется.
Post v6.5, большинство пользователей используют аутентификацию Windows для входа в SQL. Это вызывает множество сетевых вызовов между серверами и некоторую задержку. Kerberos Security еще более болтлива, поэтому установить соединение с SQL стоит дорого. По этой причине вам нужно найти баланс между удерживанием соединения открытым для жизни вашего приложения WinForms vs Открытие и закрытие его в каждом вызове метода.
В качестве приблизительного руководства, если вы думаете, что ваше приложение захочет поговорить с SQL в следующем, скажем, 30 секунд. Держите установленное соединение открытым. Если они минимизировали ваше приложение, не касались его в течение периода ожидания или у вас все данные в ОЗУ, и они вряд ли нуждаются в чем-либо больше от системы SQL. Закройте соединение.
Рассмотрите возможность создания класса с системным таймером для соединения. Ваш класс всегда будет предоставлять действительное соединение, но, возможно, класс захочет отказаться от него и освободить загрузку соединения на SQL, когда это необходимо.
Если вы также не пишете код на базе сервера, небольшое количество неэффективности памяти может даже не заметить. Но 2-10 000 клиентов, которые плохо используют ваши серверы безопасности и данных, скорее всего, приведут ваш центр данных к коленям.
Ответ 8
Любой класс, обрабатывающий SQL-материалы, такие как Connections, должен реализовывать интерфейс IDisposable, как указано в инструкциях Microsoft.NET по кодированию.
Таким образом, вероятно, вы должны закрыть и удалить свое соединение в методе Dispose.