轮询数据库时最好的方法是什么?

时间:2018-03-21 20:20:42

标签: c# database wpf task

目前我正在进行一项任务,我需要访问n个服务器的数据库以获取一些结果。我通过迭代服务器列表并为集合中的每个服务器提升每个任务来实现这一目标。该任务调用一个函数,它基本上与数据库建立连接,运行查询并断开与数据库的连接。

我的问题是我做的是通过在每次轮询数据库上建立新连接并每次关闭它,或者这是保持数据库连接打开并获取结果然后在下一次打开它的最佳方法轮询迭代。 PollingServerTimer()每次都被定时器调用。我的轮询定时器是3秒。

这样的事情:

private void PollingServerTimer(object sender, ElapsedEventArgs e)
{            
    foreach (var item in ServerOperationCollHandler)
    {
        if (item.RebootStatus != true)
        {
            PushItemIntoQueue(item);
        }
    }
}

public void PollingServerQueue()
{
    while (isRunning)
    {
        this.waitHandle.WaitOne();

        lock (syncRoot)
        {
            if (ServerQueue.Count > 0)
            {
                ServerOperationDataModel obj;
                try
                {
                    ServerQueue.TryDequeue(out obj);

                    Task GetCountFromDbTask = new Task(() => GetCountFromDb(obj));
                    GetCountFromDbTask.Start();

                    this.waitHandle.Reset();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Problem encountered while finding iterim and recovery count");
                    isRunning = false;
                    break;
                }
            }
        }
    }
}

public void GetCountFromDb(ServerOperationDataModel obj)
{
    ServerOperationDataModel serverObject = (ServerOperationDataModel)obj;
    DataBaseHandler dbHandler = new DataBaseHandler(serverObject.DataBaseIP, serverObject.DataBasePort, serverObject.DataBaseName, serverObject.DataUserName, serverObject.DataUserPassword);

    int attempts = 0;

    do
    {
        try
        {
            dbHandler.connect();
        }
        catch (Exception ex)
        {
            break;
            serverObject.DataBaseConnectionStatus = false;
            log.Error("Connection attempt " + attempts + " failed.Retrying connection. Exception details :" + ex.ToString());
            attempts++;
        }
    } while (attempts < _connectiontRetryAttempts && !dbHandler.isConnected());

    if (dbHandler.isConnected())
    {
        /*Fetch Result and then get disconnect*/
        dbHandler.disConnect();
    }
    else
    {
        //string msgLog = "Server : " + obj.ServerComponentIdentifier + " | " + obj.IPstring + "Connection cannot be established with the DB: " + obj.DataBaseIP + " | "+ obj.DataBasePort + " | " + obj.DataBaseName + " after a series of retries";
        //LoggerUpdate.LogMessage(msgLog, LOGTYPE.POLLINGDATABASE, LoggerUpdate.ReturnLogDisplayObject(DateTime.Now, obj.ServerComponentIdentifier + "|" + obj.IPstring, Convert.ToInt16(LOGTYPE.POLLINGDATABASE), obj, msgLog));
    }
}

2 个答案:

答案 0 :(得分:2)

我根本不会担心。假设您连接到SQL Server(或类似的企业DBMS),数据库连接在客户端汇集,这意味着只有在客户端第一次连接到特定数据库时才建立连接成本很高(正式:到新的,以前看不见的连接字符串)然后每个连接到同一个数据库的成本几乎为零。

如果它不是用于池化,则应用程序服务器将无法处理查询相同数据源的数百个并发浏览器连接。每3秒钟您需要的不仅仅是一个连接,这会导致任何耗尽服务器或客户端资源的风险。

您可以阅读有关汇总工作方式的更多信息

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling

旁注:你应该稍微改进你的代码。

例如,你有

GetCountFromDb(ServerOperationDataModel obj)

但是

ServerOperationDataModel serverObject = (ServerOperationDataModel)obj;

为什么需要将obj转换为同一类型的另一个变量?

catch子句中,您有break及其下方的一些代码,看起来无法访问。

答案 1 :(得分:1)

查看.NET SqlDependency对象。这允许您向数据库注册查询,并使用OnChange处理程序在查询结果发生更改时接收通知。