在不抛出异常的情况下测试SQL连接

8

为了测试我是否能够连接到我的数据库,我执行了以下代码:

using (SqlConnection connection = new SqlConnection(myConnectionString))
{
   try
   {
      connection.Open();
      canConnect = true;
   }
   catch (SqlException) { }
}

这个方法可以工作,但是如果连接失败会抛出异常。有没有其他方法可以测试Sql连接而不会抛出异常?

编辑: 为了更加精确,我想知道是否有一种简单的方法可以在不打开连接并捕获可能发生的异常的情况下完成测试。


为什么你想要避免异常? - CResults
7个回答

12

在尝试打开连接时,如果无法打开连接,则无法避免异常。它可以隐藏在某个函数中,但无论如何,您都将收到异常。

这样设计的原因是因为通常您期望能够连接到数据库。连接失败是一个例外情况

话虽如此,您可以通过检查State属性随时测试当前连接状态。


3

这样编写扩展程序:

public static class Extension{
 public static bool CanOpen(this SqlConnection connection){
   try{
    if(connection == null){ return false; }

    connection.Open();
    var canOpen = connection.State == ConnectionState.Open;
    connection.close();
    return canOpen;
 }
 catch{
  return false;
 }
}

然后您可以像这样使用它:
 using(var connection = new SqlConnection(myConnectionString)){
      if(connection.CanOpen()){
       // NOTE: The connection is not open at this point...
       // You can either open it here or not close it in the extension method...
       // I prefer opening the connection explicitly here...
     }
}

HTH.


回答不错,但是伙计,你抛出了一个异常。 - CResults
@CResults:在扩展方法的catch块中没有THROW,这样就有效地吞噬了异常。我更喜欢抛出此异常,但OP提到他在检查是否可以打开连接时不想抛出异常,因此我的解决方案是这样的。 - Sunny
请注意此解决方案,如果连接池可用,则_SqlConnection.Open()_将从池中获取连接。然后即使连接已损坏(例如TCP通道关闭),_State_也将为_Open_。然后只有在执行命令时才会引发异常。解决方法是使用_Connection.ChangeDatabase(Connection.Database);_来检查连接是否可用。 - JoeBilly

3
如果在 catch 块中抛出异常,那么您已经知道连接失败了。我认为您已经回答了自己的问题。

1

我认为这里的真正答案是ping。

string data = "ismyserverpingable";
byte[] buffer = Encoding.ASCII.GetBytes (data);
int timeout = 120;
PingReply reply = pingSender.Send ("google.com", timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
}

除非你明确地检查 SQL 连接是否可行,否则 9/10 的情况下你应该知道某个东西是否是 SQL 服务器。这将为你节省那些令人讨厌的异常内存使用,我敢打赌这正是你真正想要的。


1

连接数据库时难免会出现异常,但有一些函数可以很好地处理这种情况。我正在使用这个函数,如果连接存在,则返回true。

    public static bool IsSQLConnectionAvailable()
    {
        SqlConnection _objConn = new SqlConnection();

        try
        {
            _objConn.ConnectionString = ConfigurationManager.ConnectionStrings["DefaultSQLConnectionString"].ConnectionString;
            _objConn.Open();
        }
        catch
        {
            return false;
        }
        finally
        {
            if (_objConn.State == ConnectionState.Open)
                _objConn.Close();
        }

        return true;
    }

0
你可以使用 ConnectionStringBuilder 类,在尝试打开连接之前检查连接字符串所需的每个部分是否存在。
如果连接字符串正确,但是你要连接的数据库服务器已经关闭,你仍然会收到一个异常。如果你连接的终端可能处于离线状态,检查字符串的质量就有点毫无意义了。

0
我想分享我实现的整个解决方案,以避免在每次调用时检查连接。如果连接字符串错误,则会停止执行异常,否则将为每个连接字符串仅尝试打开一次连接字符串。
由于连接经常是多线程的,因此我添加了一个由锁使用的同步对象来进行检查。
#if DEBUG

private static object syncobj = new object();

private static ConcurrentDictionary<string, bool> CheckedConnection = new ConcurrentDictionary<string, bool>();

private static void CheckCanOpenConnection(SqlConnection connection)
{
    lock (syncobj)
    {
        try
        {
            CheckedConnection.TryGetValue(connection.ConnectionString, out bool found);
            if (found)
            {
                return;
            }
            else
            {
                connection.Open();
                var canOpen = connection.State == ConnectionState.Open;
                connection.Close();

                CheckedConnection.TryAdd(connection.ConnectionString, true);
                return;
            }
        }
        catch
        {
            throw new ApplicationException("Unable to connect to: " + connection.ConnectionString);
        }
    }
}

#endif

这里是调用实例化连接方法的代码

    private SqlConnection CreateConnection()
    {
        if (_connection == null)
        {
            _connection = new SqlConnection(this.ConnectionString);

#if DEBUG
            CheckCanOpenConnection(_connection);
#endif

        }
        return _connection;
    }

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