Должен ли я Close () для SQLConnection перед его удалением?

113

В соответствии с моим другим вопросом об одноразовых объектах , следует ли вызывать Close () перед концом блока using?

using (SqlConnection connection = new SqlConnection())
using (SqlCommand command = new SqlCommand())
{
    command.CommandText = "INSERT INTO YourMom (Amount) VALUES (1)";
    command.CommandType = System.Data.CommandType.Text;

    connection.Open();
    command.ExecuteNonQuery();

    // Is this call necessary?
    connection.Close();
}
Джон Бубриски
источник

Ответы:

107

Поскольку у вас есть блок using, будет вызван метод Dispose SQLCommand, который закроет соединение:

// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
CMS
источник
1
Делает это ._poolGroup = null; означает, что соединение не возвращается в пул соединений? так что у меня будет n-1 соединений?
Рой Намир
25

Разборка SqlConnection с использованием .NET Reflector :

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }

    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

Он вызывает Close () внутри Dispose ()

Statenjason
источник
1
@statenjason: не могли бы вы сказать, как вы можете воспользоваться преимуществами использования отражателя .net линии дизассемблеров?
odiseh
3
@odiseh просто скачайте .NET Reflector, запустите Reflector.exe, и вы сможете открыть любую .NET DLL (включая стандартную библиотеку). Он предоставляет вам древовидную структуру, аналогичную обозревателю объектов Visual Studio, однако вы можете щелкнуть правой кнопкой мыши любой класс или метод и нажать «дизассемблировать», он вернет вам исходный код на C # или VB, в зависимости от того, что вы выбрали в параметры.
Statenjason
20

Ключевое слово using правильно закроет соединение, поэтому дополнительный вызов Close не требуется.

Из статьи MSDN о пуле подключений SQL Server :

"Мы настоятельно рекомендуем вам всегда закрывать соединение, когда вы закончите его использовать, чтобы соединение было возвращено в пул. Вы можете сделать это, используя методы Close или Dispose объекта Connection, или открыв все соединения внутри оператор using в C # "

Фактическая реализация SqlConnection.Dispose с использованием .NET Reflector выглядит следующим образом:

// System.Data.SqlClient.SqlConnection.Dispose disassemble
protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
Томас Братт
источник
1
+1 для ссылки MSDN - мне нравится отражатель \ ILspy, как и следующий парень, но документы - это то место, где я хотел бы найти свои ответы.
mlhDev
5

Используя Reflector , вы можете увидеть, что Disposeметод SqlConnectionдействительно вызывает Close();

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
Аарон Дэниелс
источник
3

Нет, блокировка Using Dispose()все равно вызывает вас, поэтому в этом нет необходимости Close().

Джейсон Эванс
источник
Извините, я должен был сказать, что для большинства объектов, реализующих IDisposable и имеющих метод Close (), вызов Close () в любом случае заканчивается вызовом Dispose () за кулисами для вас.
Джейсон Эванс,
6
Разве это не наоборот - Dispose()звонки Close(), а не наоборот?
Город
1
Обычно и то, и другое. По какой-то причине они решили реализовать то, что Close также будет вызывать Dispose. Для SqlConnection это не имеет большого значения, но StreamWriters выдаст исключение, если вы закроете их, а затем удалите их. Я предполагаю, что они не изменят такое поведение просто потому, что люди теперь этого ожидают.
2

Нет, нет необходимости закрывать соединение перед вызовом Dispose.

Некоторые объекты (например, SQLConnections) можно повторно использовать после вызова Close, но не после вызова Dispose. Для других объектов вызов Close аналогичен вызову Dispose. (ManualResetEvent и Streams, я думаю, ведут себя так)

pipTheGeek
источник
1

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

blparker
источник