Чи потрібно закривати () SQLC-з'єднання, перш ніж його утилізувати?


113

Згідно з моїм іншим запитанням про одноразові об'єкти , чи слід називати Close () до кінця використовуючого блоку?

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

Оскільки у вас є блок використання, викличеться метод 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);
}

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 ()


1
@statenjason: не могли б ви сказати, що як ви скористаєтесь використанням розбиральних ліній .net відбивача?
odiseh

3
@odiseh просто завантажте .NET Reflector, запустіть reflector.exe, і ви можете відкрити будь-яку .net DLL (включаючи стандартну бібліотеку). Він надає вам структуру дерева, подібну до об’єктового браузера Visual Studio, проте ви можете клацнути правою кнопкою миші на будь-якому класі чи методі та натиснути "розібрати", після чого поверне джерело до C # або VB, залежно від того, що ви вибрали в варіанти.
statenjason

20

Ключове слово, що використовується, перерве з'єднання правильно, тому додатковий дзвінок на Закрити не потрібно.

З статті MSDN про Об'єднання підключення до SQL Server :

"Ми настійно рекомендуємо завжди закривати з'єднання, коли ви закінчите його використовувати, щоб з'єднання було повернуто в пул. Це можна зробити, використовуючи методи закриття або розпорядження об'єкта Connection, або відкривши всі з'єднання всередині за допомогою оператора 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

Ні, якщо Dispose()ви все одно використовуєте блок "Дзвінки" для вас, тому дзвонити не потрібно Close().


Вибачте, я мав би сказати, що для більшості об'єктів, які реалізують IDisposable і мають метод Close (), виклик Close () все одно закінчує виклик Dispose () за кадром для вас.
Джейсон Еванс

6
Чи не навпаки - Dispose()дзвінки Close(), а не навпаки?
місто

1
Це і те, і інше. Чомусь вони вирішили застосувати те, що Близький також закликає розпоряджатися. Для SqlConnection це не велика справа, але StreamWriters викине виняток, якщо ви закриєте, а потім розпорядьте їх. Я гадаю, що вони не змінить такої поведінки, просто тому, що зараз очікували люди.

2

Ні, не потрібно закривати з'єднання перед тим, як зателефонувати в розпорядження.

Деякі об'єкти (наприклад, SQLConnections) можна повторно використовувати, коли викликуме Close, але не після виклику Dispose. Для інших об'єктів виклик Close - це те саме, що викликати Dispose. (ManualResetEvent і Streams, я думаю, поводяться так)


1

Ні, клас SqlConnection успадковується від IDisposable, і коли стикається кінець використання (для об’єкта з'єднання), він автоматично викликає Dispose на клас SqlConnection.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.