以编程方式测试SQL Server连接的最佳方法是什么?


78

我需要开发一个例程,该例程每5分钟触发一次,以检查SQL Server列表(10到12个)是否已启动并正在运行。

我可以尝试在每台服务器上获取一个简单的查询,但这意味着我必须在每台服务器上创建表,视图或存储过程,即使我使用的是已经制作的SP,我也需要在每台服务器上都有一个注册用户服务器也是。服务器不在同一物理位置,因此具有这些要求将是一项复杂的任务。有没有一种方法可以简单地从C#一个SQL Server“ ping”?

提前致谢!


2
仅对服务器执行ping操作是不够的,服务器可能正在运行,但SQL实例已停止。最好创建一个与实例的实际ado.net连接。
罗里

您是否知道网站上唯一的问题是mssql从另外1/2百万个其他问题中标记出来的?您真的认为这是一个好标签吗?您来这里已经足够长的时间了,以了解更多。
乔尔·科恩荷恩

2
如您所知,MS-SQL和SQL-server之间有很大的区别,特别是如果我们正在谈论端口并对其进行ping操作。多么民主,每个人都必须使用相同的标签。没有选择!您应该添加另一个标签没问题,但是为什么要取出我选择的标签呢!
backslash10年

2
MS-SQL IS SQL Server-产品名称为IS SQL Server。
marc_s

8
SQL Server可以指:-任何实现结构化查询语言的数据库服务器-Microsoft SQL Server,Microsoft的特定实现数据库服务器-Sybase SQL Server,由Sybase开发的关系数据库服务器。-------如您所见,SQL Server的含义不只一个,这就是为什么我使用MSSQL标记的原因
backslash17 2010年

Answers:


75

执行SELECT 1并检查ExecuteScalar是否返回1。


1
很好,不需要在数据库中创建任何对象,但是我需要一个数据库和一个用户来进行查询。我只想知道该服务是否在MSSQL端口中启动。无论如何,您正在解决几乎75%的问题。这将是一个选择。
backslash17年

5
无论如何,您都有master db :)检查SQL Server是否正在运行的最干净方法是连接到它。要连接,您需要数据库并仍然登录。所有其他解决方案(例如ping SQL Server端口)都不能保证SQL Server正常运行,并且任何人都可以连接到它。
Andrew Bezzub 2010年

当我的真正意图是投票时,我意外地否决了这个答案。我一天后才意识到这一点,所以我再也无法纠正我的错误了。
Giorgos Betsos '19

1
@GiorgosBetsos-我纠正了您的错误:-D
KunalB。

80

当服务器的连接被停止或暂停时,我在使用EF时遇到了困难,我提出了同样的问题。因此,为了完整地回答上述问题,以下是代码。

/// <summary>
/// Test that the server is connected
/// </summary>
/// <param name="connectionString">The connection string</param>
/// <returns>true if the connection is opened</returns>
private static bool IsServerConnected(string connectionString)
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        try
        {
            connection.Open();
            return true;
        }
        catch (SqlException)
        {
            return false;
        }
    }
}

14
connection.Close();在这种情况下不需要,using子句将在终止时为您完成。

3
您应该将try catch置于using语句之外。(stackoverflow.com/q/4590490/1248177stackoverflow.com/q/6145245/1248177)。
aloisdg移至codidact.com

1
@aloisdg-取决于不是,他们是否在测试是否可以连接到数据库,并且仅在特殊情况下无法连接,否则返回false。或者也可以通过吞咽异常来错误地构造SQL连接,我知道有一个区别,因为我刚刚针对上述代码进行了编码。
brumScouse '17

13

请参阅GitHub上的以下项目:https : //github.com/ghuntley/csharp-mssql-connectivity-tester

try
{
    Console.WriteLine("Connecting to: {0}", AppConfig.ConnectionString);
    using (var connection = new SqlConnection(AppConfig.ConnectionString))
    {
        var query = "select 1";
        Console.WriteLine("Executing: {0}", query);

        var command = new SqlCommand(query, connection);

        connection.Open();
        Console.WriteLine("SQL Connection successful.");

        command.ExecuteScalar();
        Console.WriteLine("SQL Query execution successful.");
    }
}
catch (Exception ex)
{
    Console.WriteLine("Failure: {0}", ex.Message);
}

7

不会建立与数据库的连接吗?如果数据库没有启动,您将无法建立连接。


实际上,只需使用ADO net进行连接-如果在超时时间内没有响应,则数据库不可用。您无需发出查询即可确定这一点。
Dan Diplo

要使用ADO.NET进行检查,我需要一个用户,我只想检查该服务是否已启动并正在运行,而数据库是否已启动则没有问题。我需要像telnet这样的SMTP服务器。无需用户来获得响应。
backslash17年

3
@ backslash17:“用户登录失败...”响应应足以确认1)计算机已启动,2)服务正在运行。如果连接超时,则该服务无法运行/正常工作。
罗里

@Rory:好点!只是在try / catch块中检查错误的问题。谢谢!
backslash17年

@ backslash17检查“用户登录失败”是否具有单独的错误代码或可以帮助您确定错误的代码。通过异常消息区分错误是非常不好的做法。
Andrew Bezzub 2010年

1

在端口1433(默认端口)上查找打开的侦听器。如果在此处创建tcp连接后收到任何响应,则服务器可能已启动。


对于Joel Coehorn的建议,您是否已经尝试过tcping [ elifulkerson.com/projects/tcping.php]。它是一个独立的可执行文件,可让您在每个指定的时间间隔ping通。它不是在C#中。另外..我不确定如果目标计算机安装了防火墙..mmmm ..
Ashish Gupta 2010年

1

对于Joel Coehorn的建议,您是否已尝试过名为tcping的实用程序。我知道这是您没有以编程方式执行的操作。它是一个独立的可执行文件,可让您在每个指定的时间间隔ping通。它不是在C#中。另外..我不确定如果目标机器装有防火墙..hmmm ..

[我是这个网站的新手,错误地将其添加为评论,现在将其添加为答案。让我知道是否可以在这里完成,因为我在这里有重复的评论(作为评论和答案)。我无法在此处删除评论。]


0
public static class SqlConnectionExtension
{
    #region Public Methods

    public static bool ExIsOpen(this SqlConnection connection, MessageString errorMsg)
    {
        if (connection == null) return false;
        if (connection.State != ConnectionState.Open)
        {
            try
            {
                connection.Open();
            }
            catch (Exception ex) { errorMsg.Append(ex.ToString()); }
        }
        return true;
    }

    public static bool ExIsReady(this SqlConnection connction, MessageString errorMsg)
    {
        if (ExIsOpen(connction, errorMsg) == false) return false;
        try
        {
            using (SqlCommand command = new SqlCommand("select 1", connction))
            using (SqlDataReader reader = command.ExecuteReader())
                if (reader.Read()) return true;
        }
        catch (Exception ex) { errorMsg.Append(ex.ToString()); }
        return false;
    }

    #endregion Public Methods
}



public class MessageString : IDisposable
{
    #region Protected Fields

    protected StringBuilder _messageBuilder = new StringBuilder();

    #endregion Protected Fields

    #region Public Constructors

    public MessageString()
    {
    }

    public MessageString(int capacity)
    {
        _messageBuilder.Capacity = capacity;
    }

    public MessageString(string value)
    {
        _messageBuilder.Append(value);
    }

    #endregion Public Constructors

    #region Public Properties

    public int Length {
        get { return _messageBuilder.Length; }
        set { _messageBuilder.Length = value; }
    }

    public int MaxCapacity {
        get { return _messageBuilder.MaxCapacity; }
    }

    #endregion Public Properties

    #region Public Methods

    public static implicit operator string(MessageString ms)
    {
        return ms.ToString();
    }

    public static MessageString operator +(MessageString ms1, MessageString ms2)
    {
        MessageString ms = new MessageString(ms1.Length + ms2.Length);
        ms.Append(ms1.ToString());
        ms.Append(ms2.ToString());
        return ms;
    }

    public MessageString Append<T>(T value) where T : IConvertible
    {
        _messageBuilder.Append(value);
        return this;
    }

    public MessageString Append(string value)
    {
        return Append<string>(value);
    }

    public MessageString Append(MessageString ms)
    {
        return Append(ms.ToString());
    }

    public MessageString AppendFormat(string format, params object[] args)
    {
        _messageBuilder.AppendFormat(CultureInfo.InvariantCulture, format, args);
        return this;
    }

    public MessageString AppendLine()
    {
        _messageBuilder.AppendLine();
        return this;
    }

    public MessageString AppendLine(string value)
    {
        _messageBuilder.AppendLine(value);
        return this;
    }

    public MessageString AppendLine(MessageString ms)
    {
        _messageBuilder.AppendLine(ms.ToString());
        return this;
    }

    public MessageString AppendLine<T>(T value) where T : IConvertible
    {
        Append<T>(value);
        AppendLine();
        return this;
    }

    public MessageString Clear()
    {
        _messageBuilder.Clear();
        return this;
    }

    public void Dispose()
    {
        _messageBuilder.Clear();
        _messageBuilder = null;
    }

    public int EnsureCapacity(int capacity)
    {
        return _messageBuilder.EnsureCapacity(capacity);
    }

    public bool Equals(MessageString ms)
    {
        return Equals(ms.ToString());
    }

    public bool Equals(StringBuilder sb)
    {
        return _messageBuilder.Equals(sb);
    }

    public bool Equals(string value)
    {
        return Equals(new StringBuilder(value));
    }

    public MessageString Insert<T>(int index, T value)
    {
        _messageBuilder.Insert(index, value);
        return this;
    }

    public MessageString Remove(int startIndex, int length)
    {
        _messageBuilder.Remove(startIndex, length);
        return this;
    }

    public MessageString Replace(char oldChar, char newChar)
    {
        _messageBuilder.Replace(oldChar, newChar);
        return this;
    }

    public MessageString Replace(string oldValue, string newValue)
    {
        _messageBuilder.Replace(oldValue, newValue);
        return this;
    }

    public MessageString Replace(char oldChar, char newChar, int startIndex, int count)
    {
        _messageBuilder.Replace(oldChar, newChar, startIndex, count);
        return this;
    }

    public MessageString Replace(string oldValue, string newValue, int startIndex, int count)
    {
        _messageBuilder.Replace(oldValue, newValue, startIndex, count);
        return this;
    }

    public override string ToString()
    {
        return _messageBuilder.ToString();
    }

    public string ToString(int startIndex, int length)
    {
        return _messageBuilder.ToString(startIndex, length);
    }

    #endregion Public Methods
}

0

与安德鲁提供的答案类似,但我使用:

选择GetDate()作为CurrentDate

这使我可以查看SQL Server和客户端在同一操作中是否存在任何时区差异问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.