如何检查数据库是否可用

28

我有以下代码用于测试数据库连接,它定期运行以测试数据库是否可用:

private bool CheckDbConn()
{
   SqlConnection conn = null;
   bool result = true;

   try
   {
       conn = DBConnection.getNewCon();
       ConnectionState conState = conn.State;

       if (conState == ConnectionState.Closed || conState == ConnectionState.Broken)
       {
          logger.Warn(LogTopicEnum.Agent, "Connection failed in DB connection test on CheckDBConnection");
          return false;
       }             
   }
   catch (Exception ex)
   {
      logger.Warn(LogTopicEnum.Agent, "Error in DB connection test on CheckDBConnection", ex);
      return false; // any error is considered as db connection error for now
   }
   finally
   {
      try
      {
         if (conn != null)
         {
            conn.Close();
         }
      }
      catch (Exception ex)
      {
         logger.Warn(LogTopicEnum.Agent, "Error closing connection on CheckDBConnection", ex);
         result = false;
      }
   }
   return result;
}

而且:

static public SqlConnection getNewCon()
{
    SqlConnection newCon = new SqlConnection();
    newCon.ConnectionString = DBConnection.ConnectionString; // m_con.ConnectionString;
    newCon.Open();
    return newCon;
}

我的问题是:这个会按照预期工作吗?

特别是,我担心测试ConnectionState。是否可能状态是:连接中(因为Open()是同步的)?

那种情况下我该怎么办?


我不能进行注释,因此也要避免捕获一般的异常“catch(Exception ex)”,并尝试捕获像上面的例子中那样的特定异常“catch(SqlException ex)”。 - shadow
7个回答

57
你可以试试这样做。
    public bool IsServerConnected()
    {
        using (var l_oConnection = new SqlConnection(DBConnection.ConnectionString))
        {
            try
            {
                l_oConnection.Open();
                return true;
            }
            catch (SqlException)
            {
                return false;
            }
        }
    }

如果在 finally 块中 l_oConnection.Close(); 抛出异常会怎么样? - omer schleifer
1
使用 close 和 dispose 关闭连接,无需先 close 再 dispose。 - Steve
我曾经使用这个,但发现在数据库离线后的第一次调用返回了true。这是使用.Net 3.5针对sql server 2012数据库的情况。 - monty

13

SqlConnection在无法连接服务器时会抛出SqlException异常。

public static class SqlExtensions
{
    public static bool IsAvailable(this SqlConnection connection)
    {
        try
        {
            connection.Open();
            connection.Close();
        }
        catch(SqlException)
        {
            return false;
        }

        return true;
    }
}

使用方法:

using(SqlConnection connection = GetConnection())
{
    if(connection.IsAvailable())
    {
        // Success
    }
}

11

你的代码看起来没问题,但是你真的需要使用IDisposable模式,还要遵循一些命名约定:

private bool CheckDbConnection(string connectionString)
{
    try
    {
        using(var connection = new SqlConnection(connectionString))
        {
            connection.Open();
            return true;
        }
    }
    catch (Exception ex)
    {
        logger.Warn(LogTopicEnum.Agent, "Error in DB connection test on CheckDBConnection", ex);
        return false; // any error is considered as db connection error for now
    }
}

connection.Close()不应该抛出异常。只需使用using块,就可以轻松完成。

无需测试Close状态,因为您刚打开它。
了解更多关于Broken状态的信息:

Broken 与数据源的连接已断开。这只能在连接已打开后发生。处于此状态的连接可能会关闭,然后重新打开。(此值保留供产品的未来版本使用。)

所以,实际上也没必要进行测试。

如果您处于多线程环境并且您的连接实例是共享的,则可以捕获Connecting状态。但这不是您在此处的情况。


3

调用此代码不会阻塞用户界面。

public static class DatabaseExtensions
{
    public static async Task<bool> IsConnectionViable(this string connectionStr)
    {
        await using var sqlConn = new SqlConnection(connectionStr);
        return await sqlConn.IsConnectionViable();
    }

    public static async Task<bool> IsConnectionViable(this SqlConnection connection)
    {
        var isConnected = false;

        try
        {
            await connection.OpenAsync();
            isConnected = (connection.State == ConnectionState.Open);
        }
        catch (Exception)
        {
            // ignored
        }

        return isConnected;
    }
}

0

我曾使用@Ramesh Durai的解决方案,但发现在我的设置中(应用程序在启动后定期调用/测试;使用.Net 3.5与Sql Server 2012数据库),在将数据库脱机后第一次调用IsConnected()时返回了true。然而,在下面的ExecuteScalar()行上它抛出了预期的异常:

public bool IsConnected() {
    using (var conn = new SqlConnection(DBConnection.ConnectionString)) {
        using (var cmd = New SqlCommand("SELECT 1", conn)) {
            try {
                conn.Open();
                cmd.ExecuteScalar();
                return true;
            } catch (SqlException) {
                return false;
            }
        }
    }
}

0

不确定它与Visual Studio有什么关系,而且如果您查看帖子,它其中包含connectionState... - omer schleifer

0

这段代码是用于Mysql的。

public class Program
{
string connection = "SERVER=localhost; user id=root; password=; database=dbname";
private void Form1_Load(object sender, System.EventArgs e)
{
checkifconnected();
}

private void checkifconnected()
{
MySqlConnection connect = new MySqlConnection(connection);
try{
connect.Open();
MessageBox.Show("Database connected");
}
catch
{
MessageBox.Show("you are not connected to database");
}
}

public static void Main()
{

}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接