2012-02-15 36 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