ฉันต้องปิด () การเชื่อมต่อ SQLC ก่อนที่จะถูกกำจัดหรือไม่?


113

สำหรับคำถามอื่น ๆ ของฉันที่นี่เกี่ยวกับ Disposable objectsเราควรเรียก 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
ไม่this._poolGroup = null; หมายความว่าการเชื่อมต่อไม่ได้กลับไปที่พูลการเชื่อมต่อ? ดังนั้นฉันจะมีการเชื่อมต่อ n-1?
Royi Namir

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 ของ disassemblers ได้อย่างไร?
odiseh

3
@odiseh เพียงดาวน์โหลด. NET Reflector เรียกใช้ reflector.exe และคุณสามารถเปิด. net DLL (รวมทั้งไลบรารีมาตรฐาน) มันให้โครงสร้างต้นไม้ที่คล้ายกับเบราว์เซอร์วัตถุของ Visual Studio อย่างไรก็ตามคุณสามารถคลิกขวาที่คลาสหรือวิธีการใดก็ได้และคลิก "แยกชิ้นส่วน" จากนั้นจะส่งคืนแหล่งที่มาให้คุณใน C # หรือ VB แล้วแต่ว่าคุณจะเลือกไว้ใน ตัวเลือก.
statenjason

20

คำสำคัญที่ใช้จะปิดการเชื่อมต่ออย่างถูกต้องดังนั้นจึงไม่จำเป็นต้องเรียกพิเศษเพื่อปิด

จากบทความ MSDN เรื่อง SQL Server Connection Pooling :

"เราขอแนะนำอย่างยิ่งให้คุณปิดการเชื่อมต่อทุกครั้งเมื่อคุณใช้งานเสร็จแล้วเพื่อให้การเชื่อมต่อกลับไปที่พูลคุณสามารถทำได้โดยใช้วิธีปิดหรือกำจัดของวัตถุการเชื่อมต่อหรือ การเชื่อมต่อโดยการเปิดการเชื่อมต่อทั้งหมดภายใน a โดยใช้คำสั่ง ใน 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



3

ไม่ได้มีการใช้โทรบล็อกสำหรับคุณอยู่แล้วจึงมีความจำเป็นต่อการเรียกร้องใดDispose()Close()


ขออภัยฉันควรจะบอกว่าสำหรับอ็อบเจ็กต์ส่วนใหญ่ที่ใช้ IDisposable และมีเมธอด Close () การเรียก Close () จะลงท้ายด้วยการเรียก Dispose () อยู่เบื้องหลังสำหรับคุณ
Jason Evans

6
นั่นไม่ใช่วิธีอื่น - การDispose()โทรClose()ไม่ใช่ในทางกลับกัน?
Town

1
มันเป็นทั้งสองอย่างโดยปกติ ด้วยเหตุผลบางประการพวกเขาตัดสินใจที่จะใช้การปิดนั้นจะเรียกว่า Dispose เช่นกัน สำหรับ SqlConnection นี่ไม่ใช่เรื่องใหญ่ แต่ StreamWriters จะให้ข้อยกเว้นหากคุณปิดแล้วทิ้ง ฉันเดาว่าพวกเขาจะไม่เปลี่ยนพฤติกรรมนั้นเพียงเพราะเป็นสิ่งที่ผู้คนคาดหวังในตอนนี้

2

ไม่จำเป็นต้องปิดการเชื่อมต่อก่อนที่จะเรียก Dispose

อ็อบเจ็กต์บางอย่าง (เช่น SQLConnections) สามารถใช้ซ้ำได้โดยอ้างถึงการเรียกปิด แต่ไม่สามารถใช้หลังจากเรียก Dispose สำหรับวัตถุอื่น ๆ การเรียก Close จะเหมือนกับการเรียก Dispose (ManualResetEvent และ Streams ฉันคิดว่ามีพฤติกรรมเช่นนี้)


1

ไม่คลาส SqlConnection สืบทอดมาจาก IDisposable และเมื่อพบจุดสิ้นสุดของการใช้งาน (สำหรับอ็อบเจ็กต์การเชื่อมต่อ) จะเรียก Dispose บนคลาส SqlConnection โดยอัตโนมัติ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.