2012-02-15 75 views
1

我的WCF服務需要檢查的是現在可用的連接,我們可以使用它嗎?我們有很多遠程dbs。它們的連接有時很奇怪,不能用於查詢數據或其他數據。 因此,舉例來說,這是經常使用的連接字符串:驗證oracle db連接的一些棘手的快速方法

User Id=user;[email protected];Data Source=NVDB1;Connection Timeout=30 

這裏是服務的方法,用於獲取

public List<string> GetAliveDBs(string city) 
    { 
     if (String.IsNullOrEmpty(city)) 
      return null;       

     List<string> cityDbs = (from l in alldbs where !String.IsNullOrEmpty(l.Value.city) && l.Value.city.ToUpper() == city.ToUpper() select l.Value.connString).ToList();    

     // There is no such city databases 
     if (cityDbs.Count == 0) 
      return null; 

     ReaderWriterLockSlim locker = new ReaderWriterLockSlim(); 

     Parallel.ForEach(cityDbs, p => 
     { 
      if (!IsConnectionActive(p.connString)) 
      { 
       locker.EnterWriteLock(); 
       try 
       { 
        cityDbs.RemoveAt(cityDbs.IndexOf(p)); 
       } 
       finally 
       { 
        locker.ExitWriteLock(); 
       } 
      } 
     }); 

     return cityDbs; 
    } 

    static public bool IsConnectionAlive(string connectionString) 
    { 
     using (OracleConnection c = new OracleConnection(connectionString)) 
     { 
      try 
      {      
       c.Open(); 
       if ((c.State == ConnectionState.Open) && (c.Ping())) 
        return true; 
       else 
        return false; 
      } 
      catch (Exception exc) 
      { 
       return false;     
      } 
     } 
    } 

我用devart組件與Oracle數據庫進行通信。 希望你的幫助,夥計們!提前致謝!

+1

如果您問如何確定您的Oracle連接字符串是否有效,請嘗試連接到它,如果失敗則無效。如果你追求別的東西,你應該在你的*問題*中包含一個問題。 – 2012-02-15 03:26:10

+0

@ M.Babcock問題是連接檢查你建議非常慢,它不能用於快速檢查。順便說一句,問題在於問題的標題。 – kseen 2012-02-15 03:32:17

+0

我一定錯過了問號。如果你想要一個輕量級的方法來預先檢查服務器是否在那裏,然後打開一個telnet連接到它的端口。 – 2012-02-15 03:36:39

回答

1

如果目標是簡單地確定服務器是否住在IP地址或主機名,那麼我建議平安(NO 3握手,而且具有更少的開銷比UDP報文)。您可以使用System.Net.NetworkInformation.Ping類(請參閱其documentation爲例)。

如果您希望證明實際上有在Oracle端口上偵聽的東西,我建議使用System.Net.Sockets.TcpClientSystem.Net.Sockets.Socket類(它們的文檔也提供了示例)來提供此功能。

執行此操作的最簡單方法是使用C#的Oracle API打開連接。有一個非常好的教程,其中包括代碼here。它涵蓋的不僅僅是連接,而且應該能夠從其餘部分去除連接部分以適應您的需求。

2

嘗試執行一個非常低的成本操作,無論您連接的是哪種模式都應該可以工作。

選擇1

(這句話適用於MS SQL和MySQL ...應該在甲骨文工作過,但我無法證實)。

如果你得到你期望的結果(在這種情況下,一行,一列,包含「1」),那麼連接是有效的。

至少有一個連接池管理器使用此策略來定期驗證連接。

更新:

下面是您的方法的SQL Server版本。您可能只需將「Sql」替換爲「Oracle」即可。

static public bool IsConnectionAlive(string connectionString) 
{ 
    try 
    { 
     using (SqlConnection conn = new SqlConnection(connectionString)) 
     { 
      conn.Open(); 
      using (SqlCommand cmd = new SqlCommand("SELECT 1", conn)) 
      { 
       int result = (int)cmd.ExecuteScalar(); 
       return (result == 1); 
      } 

     } 
    } 
    catch (Exception ex) 
    { 
     // You need to decide what to do here... e.g. does a malformed connection string mean the "connection isn't alive"? 
     // Maybe return false, maybe log the error and re-throw the exception? 
     throw; 
    } 
} 
+0

這真的很有趣。你能提供一些代碼示例嗎? – kseen 2012-02-15 03:33:58

+1

代碼示例關於什麼? 'SELECT 1'? – 2012-02-15 03:42:17

+0

不,我要求重新編寫完整的「IsConnectionActive」方法?它應該如何測試連接?只需連接到它,然後嘗試執行查詢?這種方法比M.Babcock提出的方法更快嗎?你認爲如何? – kseen 2012-02-15 03:47:38

0

Oracle有products and software專門用於幫助保持高可用性,通過連接字符串上的名爲HA Events=true的設置,可以使您從連接池中刪除死連接。您的Oracle DBA需要確定您的安裝是否支持它。

+0

請你更詳細地解釋一下嗎? – kseen 2012-02-15 06:11:23

+0

從你原來的問題,它聽起來像你有不可靠的數據庫連接,並希望將它們路由到其他數據庫,如果連接關閉,是否正確? – 2012-02-15 06:13:39

+0

不,我只是想確保連接是有效的。 – kseen 2012-02-15 08:12:57