我有一個ASP.NET Web API,它使用SqlConnection
連接到數據庫。我有一個數據訪問層類,它有一個包含連接的實例變量。我這樣做了幾個方面的原因:在ASP.NET中正確配置SqlConnection?
- 調用代碼可以覆蓋在DAL類(例如,用於測試代碼)
- 也有一些情況下API控制器需要打開的構造函數的連接字符串一個SQL連接,開始一個事務,然後在提交(或回滾)事務之前調用DAL類中的幾個方法。因此,關閉並重新打開每個方法的連接將不起作用,因爲我必須保持連接處於打開狀態(甚至保留
SqlTransaction
對象的範圍 - 我會通過將它作爲一個實例變量來實現),以便不必該事務在DAL調用之間回滾。 - 它還簡化了代碼的可讀性,所以你不會複製遍佈各處的代碼來打開SQL連接。
當我對API進行壓力測試時,通過每秒提供數百次請求,我碰到了SQL連接池耗盡問題。進一步調查顯示,這似乎是因爲SQL連接沒有被處置。
我明白IDisposable
模式,但我不確定在這種情況下如何使用它。這裏是我的問題:
- 使用
using
塊,或try/catch/finally
塊,都需要被創建,使用和單一方法中完成的對象。在可能需要跨多個方法調用持續存在的事務上面的示例中,這是不可能的。 - 微軟(和SO其他職位)建議針對乾脆把呼叫
Dispose()
在對象的析構,而不是建議你做任何的我在問題中指定的選項1. - 微軟還表示,你不應該實施
IDisposable
你自己只是爲了包裝另一個管理對象的方法Dispose
,但是你應該「在完成對象時簡單地調用對象的Dispose()。」在控制器完成使用SQL連接後,如果我不確定從DAL內部執行此操作,我該怎麼做? (另外,這意味着我必須重構控制器來包裝每次調用DAL在using
塊,所以它只是拖延時間的道路。)
對我來說,理想解決方案將是當控制器完成處理並且將其對服務器的響應返回以傳送到前端時,能夠以某種方式安排在SqlConnection
對象上調用Dispose
方法。要做到這一點「手工」,我將不得不違反上面的第3點,並在我的DAL上創建我自己的Dispose
方法,然後簡單地調用SqlConnection的Dispose
。此外,這意味着我必須重構所有控制器中的許多方法以包裝using
塊中的所有DAL訪問權限。看起來ASP.NET在控制器返回時不會自動調用Dispose
,這就是連接泄漏的原因。
在任何一種情況下,它也會產生更詳細的代碼。例如:
// we only need one method call from the DAL, so let's be compact
string someData = new DAL().GetSomeData(someParam);
現在已經寫出爲:
// we have to initialize here to keep the variable from falling out of scope after the using blocks
// we also must provide some value because the using block implies try/catch.
string someData = "";
using (DAL d = new DAL()) {
someData = d.getSomeData(someParam);
}
什麼是實現這個建議的方法是什麼?
在一個更通用的平面上,您如何處理一個必須在方法調用之間持續存在的可丟棄對象(例如作爲實例變量)?在像try/catch/finally
或using
這樣的結構中使用一次性物品的需要似乎限制了它們的使用,僅限於可以在單一方法中創建和處理物體的情況。
如果您使用DI容器 - 您可以讓它在請求結束時處理您的資源。雖然我個人更喜歡自己管理關係 - 當我需要時打開,做些東西,關閉。 – Evk