What's the best way to test SQL Server connection programmatically?

C#Sql ServerDatabase Connectivity

C# Problem Overview


I need to develop a single routine that will be fired each 5 minutes to check if a list of SQL Servers (10 to 12) are up and running.

Is there a way to simply "ping" a SQL Server from C# one with minimal code and sql operational requirements?

C# Solutions


Solution 1 - C#

I have had a difficulty with the EF when the connection the server is stopped or paused, and I raised the same question. So for completeness to the above answers here is the code.

/// <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;
        }
    }
}

Solution 2 - C#

Execute SELECT 1 and check if ExecuteScalar returns 1.

Solution 3 - C#

See the following project on 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);
}

Solution 4 - C#

Wouldn't establishing a connection to the database do this for you? If the database isn't up you won't be able to establish a connection.

Solution 5 - C#

Look for an open listener on port 1433 (the default port). If you get any response after creating a tcp connection there, the server's probably up.


You know, I first wrote this in 2010. Today, I'd just try to actually connect to the server.

Solution 6 - C#

For what Joel Coehorn suggested, have you already tried the utility named tcping. I know this is something you are not doing programmatically. It is a standalone executable which allows you to ping every specified time interval. It is not in C# though. Also..I am not sure If this would work If the target machine has firewall..hmmm..

[I am kinda new to this site and mistakenly added this as a comment, now added this as an answer. Let me know If this can be done here as I have duplicate comments (as comment and as an answer) here. I can not delete comments here.]

Solution 7 - C#

public static class SqlConnectionExtension
{
    #region Public Methods

    public static bool ExIsOpen(
        this SqlConnection connection, MessageString errorMsg = null)
    {
        if (connection == null) { return false; }
        if (connection.State == ConnectionState.Open) { return true; }

        try
        {
            connection.Open();
            return true;
        }
        catch (Exception ex) { errorMsg?.Append(ex.ToString()); }
        return false;
    }

    public static bool ExIsReady(
        this SqlConnection connction, MessageString errorMsg = null)
    {
        if (connction.ExIsOpen(errorMsg) == false) { return false; }
        try
        {
            using (var command = new SqlCommand("select 1", connction))
            { return ((int)command.ExecuteScalar()) == 1; }
        }
        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
}

Solution 8 - C#

Similar to the answer offered by Andrew, but I use:

Select GetDate() as CurrentDate

This allows me to see if the SQL Server and the client have any time zone difference issues, in the same action.

Solution 9 - C#

Here is my version based on the @peterincumbria answer:

using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return await dbContext.Database.CanConnectAsync(cToken);

I'm using Observable for polling health checking by interval and handling return value of the function. try-catch is not needed here because: enter image description here

Solution 10 - C#

I normally do this by open a connection but I had some cases where a simple test via Open caused a AccessViolationException

using (SqlConnection db = new SqlConnection(conn))
{    
  db.Open(); // -- Access Violation caused by invalid Server in Connection String
}

So I did a TCP check before the open like recommanded by Joel Coehoorn. C# Code for this may be:

string targetAddress = "";
try
{
  targetAddress = GetServerFromConnectionString();
  IPAddress ipAddress = Dns.GetHostEntry(targetAddress).AddressList[0];
  IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 1433);

  using (TcpClient tcpClient = new TcpClient())
  {
       tcpClient.Connect(ipEndPoint);           
  }
            
}
catch (Exception ex)
{
    LogError($"TestViaTcp to server {targetAddress} failed '{ex.GetType().Name}': {ex.Message}");
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionbackslash17View Question on Stackoverflow
Solution 1 - C#27k1View Answer on Stackoverflow
Solution 2 - C#Andrew BezzubView Answer on Stackoverflow
Solution 3 - C#Geoffrey HuntleyView Answer on Stackoverflow
Solution 4 - C#Ken HendersonView Answer on Stackoverflow
Solution 5 - C#Joel CoehoornView Answer on Stackoverflow
Solution 6 - C#Ashish GuptaView Answer on Stackoverflow
Solution 7 - C#Final HeavenView Answer on Stackoverflow
Solution 8 - C#JustDaveNView Answer on Stackoverflow
Solution 9 - C#SerjGView Answer on Stackoverflow
Solution 10 - C#Daniel W.View Answer on Stackoverflow