[英]What does “opening a connection” actually mean?
我試圖向某人解釋為什么數據庫連接實現IDisposable,當我意識到我真的不知道“打開連接”實際意味着什么。
所以我的問題是 - 當它打開連接時,c#幾乎可以做什么?
謝謝。
實際上有兩個類涉及實現連接(實際上更多,但我正在簡化)。
其中之一是您在代碼中使用的IDbConnection
實現( SQLConnection
, NpgsqlConnection
, OracleConnection
等)。 另一個是程序集內部的“真實”連接對象,對代碼不可見。 我們現在稱之為“ RealConnection
”,雖然它的實際名稱因不同的實現而不同(例如在Npgsql中,我最熟悉的是實現,該類稱為NpgsqlConnector
)。
創建IDbConnection
,它沒有RealConnection
。 任何對數據庫執行某些操作的嘗試都將失敗。 當你Open()
它時,會發生以下情況:
RealConnection
,請將其RealConnection
並使其成為IDbConnection
的RealConnection
。 RealConnection
對象總數大於最大大小,則拋出異常。 RealConnection
。 初始化它,這將涉及打開某種網絡連接(例如TCP / IP)或文件句柄(對於像Access這樣的東西),通過數據庫的協議進行握手(因數據庫類型而異)並授權連接。 然后它成為IDbConnection
的RealConnection
。 在IDbConnection
上執行的操作將轉換為RealConnection
在其網絡連接(或其他)上執行的操作。 結果轉化為實現IDataReader
等的對象,以便為您的編程提供一致的接口。
如果IDataReader
與創建CommandBehavior.CloseConnection
,那么DataReader的獲得的“所有權” RealConnection
。
當您調用Close()
時,會發生以下某種情況:
RealConnection
將執行任何協議定義的過程以結束連接(向連接將要關閉的數據庫發送信號)並關閉網絡連接等。然后,對象可能超出范圍並可用於垃圾回收。 例外情況是如果發生CommandBehavior.CloseConnection
情況,在這種情況下,在觸發此情況的IDataReader
上調用Close()
或Dispose()
。
如果你調用Dispose()
然后按照Close()
發生相同的事情。 區別在於Dispose()
被認為是“清理”並且可以using
,而Close()
可以在生命中使用,然后是稍后的Open()
。
由於使用了RealConnection
對象以及它們被合並的事實,打開和關閉連接從相對較重的變為相對較輕。 因此,長時間保持連接打開以避免打開它們的開銷是很重要的,因此盡可能短的時間讓它們保持打開變得很重要,因為RealConnection
為您處理開銷,並且很快你使用它們,在使用之間共享池化連接的效率就越高。
還要注意, Dispose()
你已經調用了Close()
Dispose()
的IDbConnection
是可以的(它是一個規則,它應該總是安全地調用Dispose()
,無論狀態如何,實際上即使它已被調用)。 因此,如果您手動調用Close()
,那么在using
塊中建立連接仍然是好的,以便在調用Close()
之前捕獲異常發生的情況。 唯一的例外是你真正希望連接保持開放的地方; 假設您正在返回使用CommandBehavior.CloseConnection
創建的IDataReader
,在這種情況下,您不會丟棄IDbConnection
,但會丟棄讀取器。
如果您未能處置連接, RealConnection
會將RealConnection
返回池中以供重用,或者執行其關閉過程。 池將達到其限制,或者底層連接的數量將增加到破壞性能並阻止更多創建。 最終可能會調用RealConnection上的RealConnection
器並導致其被修復,但最終確定只會減少損壞並且無法依賴。 ( IDbConnection
不需要終結器,因為它是保存非托管資源和/或需要關閉的RealConnection
)。
假設除此之外還有其他一些對IDbConnection
實現唯一的處理要求也是合理的,即使分析上述內容導致您認為不必要,它仍然應該被處理掉(例外情況是CommandBehavior.CloseConnection
將所有處理負擔傳遞給IDataReader
,但是配置讀者同樣重要。
好問題。
從我對SQL連接的“底層”工作(有點有限的知識),涉及許多步驟,例如:
引擎蓋下的步驟
更不用說連接池了,我相信會涉及某種算法(如果連接字符串與已存在的池匹配一個,則連接被添加到池中,否則會創建新的連接)
IDiposable
關於SQL連接,我們實現了IDisposable,這樣當我們調用dispose(通過using指令或顯式)時,它會將連接放回連接池。 這與普通的舊sqlConnection.Close()形成鮮明對比 - 因為所有這一切都暫時關閉它,但保留該連接供以后使用。
根據我的理解,.Close()關閉與數據庫的連接,而.Dispose()調用.Close(), 然后釋放非托管資源。
記住這些要點,至少實現IDisposable是一種好習慣。
添加上面的答案...關鍵是,在“打開連接”時,可能會分配資源,這將需要超過標准的垃圾收集來恢復,即某些開放的套接字/管道/ IPC。 Dispose()方法清除了這些。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.