Apakah saya harus Menutup () sambungan SQLC sebelum dibuang?

113

Sesuai pertanyaan saya yang lain di sini tentang objek Disposable , haruskah kita memanggil Close () sebelum akhir blok penggunaan?

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();
}
John Bubriski
sumber

Jawaban:

107

Karena Anda memiliki blok penggunaan, metode Buang dari SQLCommand akan dipanggil dan akan menutup koneksi:

// 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
sumber
1
Apakah this._poolGroup = null; berarti koneksi tidak kembali ke kumpulan koneksi? jadi saya akan memiliki koneksi n-1?
Royi Namir
25

Pembongkaran SqlConnection dari menggunakan .NET Reflector :

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

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

Ini memanggil Close () di dalam Dispose ()

statenjason
sumber
1
@statenjason: dapatkah Anda mengatakan bahwa bagaimana Anda memanfaatkan penggunaan reflektor baris .net disassembler?
odiseh
3
@odiseh, cukup unduh .NET Reflector, jalankan reflector.exe, dan Anda dapat membuka DLL .net (termasuk pustaka standar). Ini memberi Anda struktur pohon yang mirip dengan browser objek Visual Studio, namun, Anda dapat mengklik kanan pada kelas atau metode apa pun dan klik "membongkar" itu kemudian akan mengembalikan sumber kepada Anda dalam C # atau VB, mana pun yang Anda pilih di pilihan.
statenjason
20

Kata kunci menggunakan akan menutup koneksi dengan benar sehingga panggilan tambahan untuk Tutup tidak diperlukan.

Dari artikel MSDN di SQL Server Connection Pooling :

"Kami sangat menganjurkan agar Anda selalu menutup koneksi ketika Anda selesai menggunakannya sehingga koneksi akan kembali ke pool. Anda dapat melakukan ini menggunakan metode Tutup atau Buang dari objek Koneksi, atau dengan membuka semua koneksi di dalam menggunakan pernyataan di C # "

Implementasi sebenarnya dari SqlConnection.Dispose menggunakan .NET Reflector adalah sebagai berikut:

// 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);
}
Thomas Bratt
sumber
1
+1 untuk tautan MSDN - Saya suka reflektor \ ILspy menyukai orang berikutnya, tetapi dokumennya adalah tempat yang ingin saya tuju untuk menemukan jawaban saya.
mlhDev
5

Dengan menggunakan Reflector , Anda dapat melihat bahwa Disposemetode SqlConnectionsebenarnya memanggil Close();

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}
Aaron Daniels
sumber
3

Tidak, tetap menggunakan panggilan blokir Dispose()untuk Anda, jadi tidak perlu menelepon Close().

Jason Evans
sumber
Maaf, saya seharusnya mengatakan bahwa untuk sebagian besar objek yang mengimplementasikan IDisposable dan memiliki metode Close (), memanggil Close () akhirnya memanggil Dispose () di belakang layar untuk Anda.
Jason Evans
6
Bukankah itu sebaliknya - Dispose()panggilan Close(), bukan sebaliknya?
Kota
1
Biasanya keduanya. Untuk beberapa alasan mereka memutuskan untuk mengimplementasikan Close yang akan memanggil Buang juga. Untuk SqlConnection, ini bukan masalah besar, tetapi StreamWriters akan mengeluarkan pengecualian jika Anda menutup dan kemudian membuangnya. Dugaan saya adalah mereka tidak akan mengubah perilaku itu hanya karena itulah yang diharapkan orang sekarang.
2

Tidak, tidak perlu Menutup koneksi sebelum memanggil Buang.

Beberapa objek, (seperti SQLConnections) dapat digunakan kembali setelah memanggil Tutup, tetapi tidak setelah memanggil Buang. Untuk objek lain, memanggil Tutup sama dengan memanggil Buang. (ManualResetEvent dan Streams menurut saya berperilaku seperti ini)

pipTheGeek
sumber
1

Tidak, kelas SqlConnection mewarisi dari IDisposable, dan ketika akhir penggunaan (untuk objek koneksi) ditemui, secara otomatis memanggil kelas Buang di SqlConnection.

blparker
sumber