2014-02-20 64 views
0

我在一個很長的運行服務中有一個非常小的數據抽象類。它是一個靜態類,作爲一個跨類實用程序被稱爲無狀態(就像DataTable someResults = Data.SelectFooFromBar()) - 我不想在幾個離散和無關的類中實例化它。該服務在出現時會提供Data.Initialize(connectionString)。該Initialize樣子:長時間維護.NET OdbcConnection對象

private static string connectionString; 
private static OdbcConnection connection; 

public static void Initialize(string mySqlConnectionString) 
{ 
    /*mySqlConnectionString would look something like this: 
    "Provider=MSDASQL; 
     Driver={MySQL ODBC 3.51 Driver}; 
     UID=some_db_user; 
     PWD=some_db_pass; 
     Server=db-host; 
     Port=3306; 
     Database=some_db; 
     Protocol=TCP; 
     Compress=false; 
     Pooling=true; 
     Min Pool Size=0; 
     Max Pool Size=100; 
     Connection Lifetime=0; 
     OPTION=16386;"*/ 

    //Ensure only one connection exists to prevent leaks, and also 
    // only modify the connection if the connection string has changed: 
    if (connection == null || connectionString != mySqlConnectionString) 
    { 
     connectionString = mySqlConnectionString; 
     connection = new OdbcConnection(connectionString); 
    } 
} 

這裏是實際進行消毒和執行查詢面向公衆的方法所使用的方法:

private static DataTable Select(string query) 
{ 
    try 
    { 
     query = Sanitize(query); 

     connection.Open(); 
     DataTable dt = new DataTable(); 
     OdbcDataAdapter da = new OdbcDataAdapter(query, connection); 
     da.Fill(dt); 
     connection.Close(); 

     return dt; 
    } 
    catch (Exception ex) 
    { 
     connection.Close(); 
     ExceptionHandler(ex, query); 
     return null; 
    } 
} 

最後一個實際的面向公衆的數據的方法:

public static DataTable SelectFooFromBar() 
{ 
    return Select("SELECT foo FROM bar"); 
} 

我的問題是確保我的connection對象總是好的最好方法是什麼?

  • 是否有可以處理的事件或連接不良時發生了什麼?
  • 每次查詢運行時打開/關閉connection對象也有好還是壞的?
  • 我應該有多個catches,所以我可以說,做一個connection.Close()就當它是一個查詢級別的錯誤移動,但到connection = new OdbcConnection(connectionString)時,我異常指示給我,我是斷開的(不知道這是哪個異常)

    它離開它似乎不好打開所有的時間,但我想獲得第二個意見。

+1

使用'using'語句。 – SLaks

+1

進行靜態連接是一個非常糟糕的主意。 – SLaks

+1

使用參數。 – SLaks

回答

2

您應該爲每個操作打開一個新的連接,而不是打開一個連接並重新使用它。

在幕後,實際的數據庫適配器將有一個連接池。當請求新連接時,它保持打開並分配的多個連接。通常創建一個新的連接是很昂貴的,但是由於連接池的原因,這個開銷在短時間內創建很多連接時根本沒有感覺到。

如果你的連接連接失敗會拋出(當然,你要確保連接池在你的數據庫配置中啓用了,但你表現出什麼基礎,這顯然已經是了。)

一個例外。讓這個例外泡沫到可以適當處理這種情況的地方。這幾乎肯定不是您的DAL,而是您的業務邏輯,在某種程度上,可以通知用戶錯誤並確定應該做些什麼。

+0

你提到這很有趣,因爲那正是它以前的樣子。問題在於Data類不斷處理大量調用,因此它會生成數千個TIME_WAIT連接,而這些連接佔用了大量必須維持連接狀態的網絡基礎結構上的大量資源。所以我決定嘗試只用一個連接來消除這個問題。 – kmarks2

+1

@ kmarks2如果您沒有足夠的資源來支持那麼多的話,請將您池中的最大連接數降低到一個更易於管理的數字。 – Servy

+0

我想我會恢復到之前的樣子(每個操作的新連接),並且會大大降低線程池大小。 Servy的建議非常感謝。 – kmarks2

0

如果您未使用連接池,請創建一個返回打開連接的函數GetConnection。在此函數內部,測試全局連接對象是否爲空或關閉。如果是這樣,請重新打開它。連接關閉並不重要,重要的是它在需要時打開。

+0

我使用的連接池。最小= 0,最大= 100。 – kmarks2

+1

您仍然需要處理多個線程同時調用DAL的任何方法 – Servy

+1

在這種情況下,池正在爲您完成大部分工作,在釋放它時並不真正關閉連接,它會返回到池中以供重用 –

1

你不應該一直打開它。你將不得不寫更多的代碼,以監視連接的狀態和處理超時的情況下,網絡連接問題等長期運行的開放連接。

你會注意到大多數人在使用中包裝連接。根據需要建立連接沒有太多的成本。

+1

因此您在說創建一個新的連接,打開它,對其進行操作並在每次查詢需要處理時關閉它? – kmarks2