Подтвердить что ты не робот

Требуется ли SqlCommand.Dispose(), если будет установлено связанное SqlConnection?

Обычно я использую такой код:

using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
{
   var command = connection.CreateCommand();
   command.CommandText = "...";
   connection.Open();
   command.ExecuteNonQuery();
}

Будет ли мой command автоматически удален? Или нет, и я должен обернуть его в блок using? Требуется ли распоряжаться SqlCommand?

4b9b3361

Ответ 1

Просто сделайте следующее:

using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
   command.CommandText = "...";
   connection.Open();
   command.ExecuteNonQuery();
}

Не вызывать dispose по команде не будет делать ничего плохого. Однако вызов Dispose на нем будет подавить вызов финализатору, заставляя вызов удалять повышение производительности.

Ответ 2

Самая безопасная политика - всегда вызывать Dispose() для объекта, если он реализует IDisposable, либо явно, либо через блок использования. Могут быть случаи, когда это не требуется, но вызов в любом случае никогда не должен вызывать проблем (если класс написан правильно). Кроме того, вы никогда не знаете, когда реализация может измениться, означая, что, когда вызов ранее не требовался, он определенно требуется.

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

Ответ 3

Да, вы должны, даже если это реализация в настоящее время не делает много, вы не знаете, как это будет изменяться в будущем (например, более новые версии фреймворка). В общем, вы должны распоряжаться всеми объектами, которые реализуют IDisposable, чтобы быть в безопасности.

Однако, если операция отложена и вы не контролируете полную область действия (например, при работе несинхронно или при возврате SqlDataReader или около того), вы можете установить CommandBehavior в CloseConnection, чтобы как только считыватель будет выполнен, соединение правильно закрыто/расположено для вас.

Ответ 4

Вы можете узнать такие вещи, используя Reflector или dotPeek или https://referencesource.microsoft.com/.

У меня было небольшое копание (я бы посоветовал вам копать себя, хотя, чтобы быть полностью уверенным в этом, хотя я и не старался так сильно), и похоже, что когда вы убиваете соединение, нет никакого избавления от каких-либо дочерних элементов, связанных с этой связью. Кроме того, на самом деле это не похоже на то, что избавление от команды действительно так много делает. Он установит в ноль поле, отсоединится от контейнера (это может предотвратить утечку управляемой памяти) и вызовет событие (это может быть важно, но я не вижу, кто слушает это событие).

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

Ответ 5

На практике вы можете пропустить Dispose. Это не освобождает любые ресурсы. Он даже не подавляет финализацию, поскольку это делает конструктор SQLCommand.

Теоретически Microsoft могла бы изменить реализацию для хранения неуправляемых ресурсов, но я надеюсь, что они выпустят API, который избавится от базового класса Component задолго до того, как они это сделают.

Ответ 6

По моему мнению, вызов 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();
}