codememo

SQL Server 연결을 프로그래밍 방식으로 테스트하는 가장 좋은 방법은 무엇입니까?

tipmemo 2023. 5. 18. 21:04
반응형

SQL Server 연결을 프로그래밍 방식으로 테스트하는 가장 좋은 방법은 무엇입니까?

SQL 서버 목록(10~12개)이 실행 중인지 확인하기 위해 5분마다 실행되는 단일 루틴을 개발해야 합니다.

코드 및 SQL 운영 요구사항을 최소화하면서 C# 서버에서 SQL 서버를 "ping"할 수 있는 방법이 있습니까?

서버 연결이 중단되거나 일시 중지될 때 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;
        }
    }
}

실행SELECT 1ExecuteScalar가 1을 반환하는지 확인합니다.

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

데이터베이스에 대한 연결을 설정하면 이 작업이 수행되지 않습니까?데이터베이스가 작동하지 않으면 연결을 설정할 수 없습니다.

Joel Coehorn이 제안한 바와 같이 tcping이라는 유틸리티는 이미 사용해 본 적이 있습니다.이것이 당신이 프로그래밍적으로 하고 있지 않다는 것을 알고 있습니다.지정된 시간 간격마다 ping을 수행할 수 있는 독립 실행형 실행 파일입니다.하지만 그것은 C#에 없습니다.또한..대상 시스템에 방화벽이 있다면 이것이 작동할지 잘 모르겠습니다..흠..

[저는 이 사이트가 처음이라 실수로 이것을 댓글로 추가했고, 이제 이것을 답변으로 추가했습니다.여기에 중복된 의견(댓글 및 답변)이 있으므로 이 작업을 수행할 수 있는지 알려주십시오.여기서 댓글을 삭제할 수 없습니다.]

포트 1433(기본 포트)에서 열린 수신기를 찾습니다.거기에 tcp 연결을 만든 후 응답을 받으면 서버가 작동 중일 수 있습니다.


2010년에 처음으로 이 글을 썼습니다.오늘은 서버에 실제로 연결하려고 합니다.

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
}

Andrew가 제시한 답변과 유사하지만, 저는 다음을 사용합니다.

GetDate()를 CurrentDate로 선택합니다.

이렇게 하면 SQL Server와 클라이언트가 동일한 작업에서 시간대 차이 문제가 있는지 확인할 수 있습니다.

다음은 @peterincumbria 답변을 기반으로 한 제 버전입니다.

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

저는 인터벌별 폴링 헬스 체크와 함수의 반환값 처리를 위해 Observable을 사용하고 있습니다. try-catch다음과 같은 이유로 여기서는 필요하지 않습니다.

저는 보통 연결을 열어 이 작업을 수행하지만, 간단한 테스트를 수행하는 경우가 있습니다.Open을 야기시켰습니다.AccessViolationException

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

그래서 조엘 코훈이 추천한 것처럼 오픈 전에 TCP 체크를 했습니다.C# 코드는 다음과 같습니다.

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}");
}

언급URL : https://stackoverflow.com/questions/2440060/whats-the-best-way-to-test-sql-server-connection-programmatically

반응형