Требуется ли закрытие / удаление SqlDataReader, если вы уже закрываете SqlConnection? - PullRequest
4 голосов
/ 17 апреля 2010

Я заметил Этот вопрос , но мой вопрос немного более конкретен.

Есть ли преимущество в использовании

using (SqlConnection conn = new SqlConnection(conStr))
{
     using (SqlCommand command = new SqlCommand())
     {
        // dostuff
     } 
}

вместо

using (SqlConnection conn = new SqlConnection(conStr))
{
     SqlCommand command = new SqlCommand();
     // dostuff
}

Очевидно, что имеет значение, если вы планируете выполнить более одной команды с одним и тем же соединением, поскольку закрытие SqlDataReader более эффективно, чем закрытие и повторное открытие соединения (вызов conn.Close();conn.Open(); также освободит соединение). 1013 *

Я вижу, что многие люди настаивают на том, что неспособность закрыть SqlDataReader означает оставить открытые ресурсы для соединения, но разве это не применимо, если вы не закрываете соединение?

Ответы [ 5 ]

16 голосов
/ 17 апреля 2010

На мой взгляд, здесь есть два правила:

  1. Классы, реализующие IDisposable, должны быть заключены в блок using.
  2. Вы не должны полагаться на реализацию класса IDisposable, чтобы игнорировать правило 1.

То есть, даже если вы знаете, что удаление объекта соединения позаботилось об удалении связанного с ним объекта команды, вам не следует полагаться на это поведение.

Кстати, можно использовать вложенные блоки более чистым способом:

using (SqlConnection conn = new SqlConnection(conStr))
using (SqlCommand command = new SqlCommand())
{
    // dostuff
}

и я бы использовал

SqlCommand command = conn.CreateCommand();

вместо создания новой SqlCommand и последующей ее привязки к соединению.

5 голосов
/ 17 апреля 2010

Технически это не нужно; закрытие SqlConnection должно уничтожить все ресурсы, которые SqlDataReader использует. Обратное также верно; вам не нужно Dispose SqlConnection, если вы располагаете SqlDataReader, который был создан с помощью CommandBehavior.CloseConnection.

Практически говоря, однако, когда класс реализует IDisposable, вы должны Dispose это, когда закончите с ним. Детали реализации каркасных классов могут быть изменены в любое время, и если в документации конкретно не указаны обстоятельства, при которых нет необходимости Dispose экземпляр, всегда существует вероятность того, что некоторые будущие изменения / обновления приведут к вашему коду с утечкой ресурса.

Это действительно не требует дополнительных усилий, поэтому просто оберните его в блок using.

1 голос
/ 17 апреля 2010

Это может быть необязательно во многих случаях, но это лучшая практика по причине. Нет причин позволять ресурсам сохраняться после того, как они перестают быть полезными. Конструкция using помогает обеспечить это.

0 голосов
/ 08 февраля 2017

Есть разница. Если вы создадите 2 этих читателей без открытия / закрытия соединения, но не утилизируете первое из них перед использованием второго, вы получите конфликт, говорящий о том, что соединение уже связано с открытым читателем .

0 голосов
/ 17 апреля 2010

Разве это не вопрос того, чтобы вы освободили ресурс сейчас, а сборщик мусора освободил его позже?

...