簡體   English   中英

“打開連接”究竟意味着什么?

[英]What does “opening a connection” actually mean?

我試圖向某人解釋為什么數據庫連接實現IDisposable,當我意識到我真的不知道“打開連接”實際意味着什么。
所以我的問題是 - 當它打開連接時,c#幾乎可以做什么?

謝謝。

實際上有兩個類涉及實現連接(實際上更多,但我正在簡化)。

其中之一是您在代碼中使用的IDbConnection實現( SQLConnectionNpgsqlConnectionOracleConnection等)。 另一個是程序集內部的“真實”連接對象,對代碼不可見。 我們現在稱之為“ RealConnection ”,雖然它的實際名稱因不同的實現而不同(例如在Npgsql中,我最熟悉的是實現,該類稱為NpgsqlConnector )。

創建IDbConnection ,它沒有RealConnection 任何對數據庫執行某些操作的嘗試都將失敗。 當你Open()它時,會發生以下情況:

  1. 如果啟用了池,並且池中存在RealConnection ,請將其RealConnection並使其成為IDbConnectionRealConnection
  2. 如果啟用了池,並且存在的RealConnection對象總數大於最大大小,則拋出異常。
  3. 否則創建一個新的RealConnection 初始化它,這將涉及打開某種網絡連接(例如TCP / IP)或文件句柄(對於像Access這樣的東西),通過數據庫的協議進行握手(因數據庫類型而異)並授權連接。 然后它成為IDbConnectionRealConnection

IDbConnection上執行的操作將轉換為RealConnection在其網絡連接(或其他)上執行的操作。 結果轉化為實現IDataReader等的對象,以便為您的編程提供一致的接口。

如果IDataReader與創建CommandBehavior.CloseConnection ,那么DataReader的獲得的“所有權” RealConnection

當您調用Close()時,會發生以下某種情況:

  1. 如果池化,並且池未滿,則將該對象放入隊列以供稍后操作使用。
  2. 否則, 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連接的“底層”工作(有點有限的知識),涉及許多步驟,例如:

引擎蓋下的步驟

  1. 物理套接字/管道打開(使用給定的驅動程序,例如ODBC)
  2. 與SQL Server的握手
  3. 協商連接字符串/憑據
  4. 交易范圍

更不用說連接池了,我相信會涉及某種算法(如果連接字符串與已存在的池匹配一個,則連接被添加到池中,否則會創建新的連接)

IDiposable

關於SQL連接,我們實現了IDisposable,這樣當我們調用dispose(通過using指令或顯式)時,它會將連接放回連接池。 這與普通的舊sqlConnection.Close()形成鮮明對比 - 因為所有這一切都暫時關閉它,但保留該連接供以后使用。

根據我的理解,.Close()關閉與數據庫的連接,而.Dispose()調用.Close(), 然后釋放非托管資源。

記住這些要點,至少實現IDisposable是一種好習慣。

添加上面的答案...關鍵是,在“打開連接”時,可能會分配資源,這將需要超過標准的垃圾收集來恢復,即某些開放的套接字/管道/ IPC。 Dispose()方法清除了這些。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM