Требуется ли SqlCommand.Dispose (), если связанный SqlConnection будет удален?
-
05-07-2019 - |
Вопрос
Я обычно использую такой код:
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
{
var command = connection.CreateCommand();
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
Будет ли моя команда
автоматически удалена? Или нет, и я должен обернуть его в блок используя
? Требуется ли утилизировать SqlCommand
?
Решение
Просто сделай это:
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
Отсутствие вызова dispose по команде ничего плохого не сделает. Однако вызов Dispose для него прервет вызов финализатора , что делает вызов распоряжаться повышением производительности.
Другие советы
Самая безопасная политика - всегда вызывать Dispose ()
для объекта, если он реализует IDisposable
, явно или через блок using. Могут быть случаи, когда это не требуется, но вызов в любом случае никогда не должен вызывать проблем (если класс написан правильно). Кроме того, вы никогда не знаете, когда реализация может измениться, а это означает, что там, где вызов ранее не требовался, теперь он определенно требуется.
В приведенном вами примере вы можете добавить дополнительный внутренний блок использования для команды, а также сохранить внешний блок использования для соединения.
Да, вы должны, даже если реализация в настоящее время не делает много, вы не знаете, как это изменится в будущем (например, в новых версиях фреймворка). В общем, вы должны располагать все объекты, которые реализуют IDisposable
, для обеспечения безопасности.
Однако, если операция отложена и вы не управляете полной областью действия (например, при асинхронной работе или при возврате SqlDataReader
или около того), вы можете установить CommandBehavior
to CloseConnection
, чтобы, как только считыватель закончил, соединение было правильно закрыто / удалено для вас.
Подобные вещи вы можете узнать, используя Reflector или dotPeek или < a href = "https://referencesource.microsoft.com/" rel = "nofollow noreferrer"> https://referencesource.microsoft.com/ .
У меня была небольшая копка (я бы посоветовал вам копать себя, хотя, чтобы быть полностью уверенным в остальном, хотя я и не старался), и похоже, что когда вы убиваете соединение, нет никакого избавления от любые дети, связанные с этой связью. Кроме того, на самом деле это не похоже на то, что избавление от команды действительно так много делает. Он установит в ноль поле, отсоединится от контейнера (это может предотвратить утечку управляемой памяти) и вызовет событие (это может быть важно, но я не вижу, кто слушает это событие).
В любом случае рекомендуется использовать этот материал в блоке using или убедиться, что вы избавляетесь от него с помощью шаблона dispose в объекте, который содержит соединение (если вы намерены некоторое время удерживать команду). р>
На практике вы можете пропустить Dispose
. Это не освобождает ресурсы. Он даже не подавляет финализацию, поскольку Конструктор SQLCommand делает это .
Теоретически Microsoft могла бы изменить реализацию для хранения неуправляемого ресурса, но я надеюсь, что они выпустят API, который избавится от базового класса Component
задолго до того, как они это сделают. что.
По моему мнению, вызов Dispose
для SqlConnection
и SqlCommand
является хорошей практикой, используйте приведенный ниже код
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
try{
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
}
catch(Exception ex){ //Log exception according to your own way
throw;
}
finally{
command.Dispose();
connection.Close();
connection.Dispose();
}