一段时间后关闭互联网连接后如何重试连接到数据库

问题描述 投票:1回答:3

我有一个用c#构建的通知应用程序,用于通知数据库中的任何更改。该应用程序在后台运行。但问题是在应用程序启动后如果关闭互联网,则应用程序抛出SQLException。我用try catch来处理异常。但我希望我的应用程序尝试连接数据库,并在建立连接时返回到主代码。

    try
            {
                using (SqlConnection connection =
       new SqlConnection(GetConnectionString()))
                {              
//i want to return here when the connection is reestablished

using (SqlCommand command =
                    new SqlCommand(GetListenerSQL(), connection))
                    {
                        connection.Open();

                        // Make sure we don't time out before the
                        // notification request times out.
                        command.CommandTimeout = NotificationTimeout;
                        SqlDataReader reader = command.ExecuteReader();
                        while (reader.Read())
                        {
                            messageText = System.Text.ASCIIEncoding.ASCII.GetString((byte[])reader.GetValue(13)).ToString();
                            // Empty queue of messages.
                            // Application logic could parse
                            // the queue data and 
                            // change its notification logic.
                        }

                        object[] args = { this, EventArgs.Empty };
                        EventHandler notify =
                        new EventHandler(OnNotificationComplete);
                        // Notify the UI thread that a notification
                        // has occurred.
                        this.BeginInvoke(notify, args);
                    }
                }
            }
            catch(SqlException e)
            {

            }

没有goto声明就可以做到这一点。我宁愿避免使用goto语句。

c# sql-server
3个回答
0
投票

我会将重试逻辑移出查询方法。我在某个地方见过一个很好的重试库,但我现在找不到它。

public void StartListener()
{                    
    var message = GetMessage(); 
    //process message in some way
    object[] args = { this, EventArgs.Empty };
    EventHandler notify = OnNotificationComplete;                
    this.BeginInvoke(notify, args);                     
}

private const int TimeoutStep = 2000;
private const int MaxTimeout = 10000;

private string GetMessage(int timeout = 0)
{
    //prevent loop of endless retries
    if (timeout >= MaxTimeout)
    {
        //optional: define your own Exception class
        throw new MaxTimeoutException();
    }

    try
    {
        Thread.Sleep(timeout);
        return GetMessageFromDatabase();
    }
    catch (SqlException ex)
    {
        //log ex in debug mode at least               
        return GetMessage(timeout + TimeoutStep);
    }             
}

private string GetMessageFromDatabase()
{
    string message = null;
    using (var connection = new SqlConnection(GetConnectionString()))
    {
        using (var command = new SqlCommand(GetListenerSQL(), connection))
        {
            connection.Open();
            command.CommandTimeout = NotificationTimeout;

            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    message = System.Text.ASCIIEncoding.ASCII.GetString((byte[])reader.GetValue(13));
                }
            }
        }
    }

    return message;
}

1
投票

从@Archer的建议我得到了解决方案。在catch块中,我再次调用该方法,该方法在一段合适的时间后使用此连接。就像是

public void StartListener()
{
try
            {
                using (SqlConnection connection =
       new SqlConnection(GetConnectionString()))
                {              
//i want to return here when the connection is reestablished

using (SqlCommand command =
                    new SqlCommand(GetListenerSQL(), connection))
                    {
                        connection.Open();

                        // Make sure we don't time out before the
                        // notification request times out.
                        command.CommandTimeout = NotificationTimeout;
                        SqlDataReader reader = command.ExecuteReader();
                        while (reader.Read())
                        {
                            messageText = System.Text.ASCIIEncoding.ASCII.GetString((byte[])reader.GetValue(13)).ToString();
                            // Empty queue of messages.
                            // Application logic could parse
                            // the queue data and 
                            // change its notification logic.
                        }

                        object[] args = { this, EventArgs.Empty };
                        EventHandler notify =
                        new EventHandler(OnNotificationComplete);
                        // Notify the UI thread that a notification
                        // has occurred.
                        this.BeginInvoke(notify, args);
                    }
                }
            }
            catch(SqlException e)
            {
                 Thread.Sleep(2000);
                 StartListener();
            }
}

0
投票

如果它失败了你应该调用一个计时器,计时器应该调用后台工作者。编写功能以检查后台工作人员的连接。如果它是真的你应该停止计时器。并调用通常的过程

© www.soinside.com 2019 - 2024. All rights reserved.