【问题标题】:Keep C# app open and check the database保持 C# 应用程序打开并检查数据库
【发布时间】:2016-01-26 16:41:16
【问题描述】:

我有这个应用程序。与一个数据库连接并向安卓设备发送通知。我想保持这个应用程序始终打开并检查数据库是否有新记录。我唯一的想法是放入一个无限循环,如 while(true) 但我在 connection.Open(); 行中有关于内存和程序的警告正在停止。

namespace AndroidParse
{
class Program
{

    static void Main(string[] args)
    {
        //SqlDataReader reader;
        SqlConnection conn = new SqlConnection();

        string queryString = "SELECT TOP 1 device_id FROM Temp ORDER BY ID_Requests DESC";
        string connectionString = "XXXX";

        while (true)
        {

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                SqlCommand command = new SqlCommand(queryString, connection);

                connection.Open();

                SqlDataReader reader = command.ExecuteReader();
                try
                {
                    while (reader.Read())
                    {



                        Console.WriteLine(reader[0]);
                        bool isPushMessageSend = false;

                        string postString = "";
                        string urlpath = "https://api.parse.com/1/push";
                        var httpWebRequest = (HttpWebRequest)WebRequest.Create(urlpath);

                        postString = "{\"data\": { \"alert\": \"Finally is working\" },\"where\": { \"device_id\": \"" + reader[0] + "\" }}";
                        httpWebRequest.ContentType = "application/json";
                        httpWebRequest.ContentLength = postString.Length;
                        httpWebRequest.Headers.Add("X-Parse-Application-Id", "XXXX");
                        httpWebRequest.Headers.Add("X-Parse-REST-API-KEY", "XXXX");
                        httpWebRequest.Method = "POST";

                        StreamWriter requestWriter = new StreamWriter(httpWebRequest.GetRequestStream());
                        requestWriter.Write(postString);
                        requestWriter.Close();
                        var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();


                        using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                        {
                            var responseText = streamReader.ReadToEnd();
                            JObject jObjRes = JObject.Parse(responseText);
                            if (Convert.ToString(jObjRes).IndexOf("true") != -1)
                            {
                                isPushMessageSend = true;
                            }
                        }
                        //--------------------------------------------------
                        SqlConnection sqlConnection1 = new SqlConnection(connectionString);
                        SqlCommand cmd = new SqlCommand();
                        SqlDataReader reader1;

                        cmd.CommandText = "delete from Temp where ID_Requests in (select top 1 ID_Requests from Temp order by ID_Requests desc)";

                        cmd.Connection = sqlConnection1;

                        sqlConnection1.Open();

                        reader1 = cmd.ExecuteReader();
                        // Data is accessible through the DataReader object here.

                        sqlConnection1.Close();
                        //--------------------------------------------------
                        Console.ReadLine();
                    }
                }
                finally
                {
                    reader.Close();
                }
                connection.Close();

            }
        }

    }

    private static void println()
    {
        throw new NotImplementedException();
    }
}

}

【问题讨论】:

  • 计时器可能更适合。
  • 您也可以将其封装在 Windows 服务中。
  • 如果您对数据库具有写入权限,只需在更新或插入时设置触发器并让它执行此脚本。否则,是的,一个计时器可能是最好的。
  • 定时器让我很开心。谢谢大家。
  • 请记住,如果您使用的是计时器(而不是数据库触发器),如果在 timer.tick 事件中进行了多次更新,那么您将只对最近的一次进行操作,因为您只选择了“TOP 1”

标签: c# sql-server infinite-loop


【解决方案1】:

使用像 Denis Reznik 建议的 SqlDependency 对象是一个很好的解决方案。 需要注意的几点:

  1. SqlDependency 要求 SQL Server Service Broker 服务在 SQL Server 上运行(更多详细信息请参见:https://msdn.microsoft.com/en-us/library/ms172133(v=vs.110).aspx

  2. 可以在SqlCommand 中使用的查询基本上是在服务器上连续执行的……因此,查询的功能有一些限制(例如,没有聚合)。此处 Smudge202 的 SO 答案中的更多详细信息:What are the limitations of SqlDependency

  3. 我发现使用SqlDependency 简单地通知更改,然后通过调用数据访问方法等进行操作...比尝试实际使用查询来检索数据更容易。因此,在您的示例中,您可能希望让SqlDependency 通知发生更改,然后创建一个单独的数据访问方法/sp / etc...来检索device_id 之类的详细信息。

这是一个基于您上面的代码的示例......它可能需要一些调整。祝你好运!

namespace AndroidParse
{
    public class DbMonitor
    {
        private readonly string _connectionString = ConfigurationManager.ConnectionStrings["XXXXX"].ConnectionString;
        private SqlDependency _dependency;
        private SqlConnection _conn;
        private SqlCommand _command;
        public void MonitorDatabase()
        {
            SqlDependency.Start(_connectionString);

            // Open DB Connection
            using (_conn = new SqlConnection(_connectionString))
            {
                // Setup SQL Command
                using (_command = new SqlCommand("SELECT TOP 1 device_id FROM Temp ORDER BY ID_Requests DESC", _conn))
                {
                    // Create a dependency and associate it with the SqlCommand. *** MAGIC ****
                    _dependency = new SqlDependency(_command);

                    // Subscribe to the SqlDependency event.
                    _dependency.OnChange += HandleDatabaseChange;

                    // Execute 
                    _command.Connection.Open();
                    _command.ExecuteReader();
                }
            }
        }

        public void Stop()
        {
            SqlDependency.Stop(_connectionString);
        }

        private void HandleDatabaseChange(object sender, SqlNotificationEventArgs e)
        {
            if (e.Info == SqlNotificationInfo.Invalid)
            {
                Console.WriteLine("The above notification query is not valid.");
            }
            else
            {
                Console.WriteLine("Database Changed based on query");
                Console.WriteLine("------------------------------------");
                Console.WriteLine("Event Details:");
                Console.WriteLine("Notification Info: " + e.Info);
                Console.WriteLine("Notification source: " + e.Source);
                Console.WriteLine("Notification type: " + e.Type);
            }

            //PushMessage logic here
            bool isPushMessageSend = false;

            string postString = "";
            string urlpath = "https://api.parse.com/1/push";
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(urlpath);

            // Use Query to get device_id? 

            postString = "{\"data\": { \"alert\": \"Finally is working\" },\"where\": { \"device_id\": \"" + "deviceID" + "\" }}";
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.ContentLength = postString.Length;
            httpWebRequest.Headers.Add("X-Parse-Application-Id", "XXXX");
            httpWebRequest.Headers.Add("X-Parse-REST-API-KEY", "XXXX");
            httpWebRequest.Method = "POST";

            StreamWriter requestWriter = new StreamWriter(httpWebRequest.GetRequestStream());
            requestWriter.Write(postString);
            requestWriter.Close();
            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();


            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                var responseText = streamReader.ReadToEnd();
                JObject jObjRes = JObject.Parse(responseText);
                if (Convert.ToString(jObjRes).IndexOf("true") != -1)
                {
                    isPushMessageSend = true;
                }
            }

            // Resume Monitoring... Requires setting up a new connection, etc.. Reuse existing connection? Tried.
            MonitorDatabase();
        }
    }
}

class Program
{

    static void Main(string[] args)
    {
        try
        {
            // Start the cheese monitor
            DbMonitor dbMonitor = new DbMonitor();
            dbMonitor.MonitorDatabase();

            Console.WriteLine("Monitoring....Press any key to stop.");
            Console.Read();

            dbMonitor.Stop();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw;
        }
        finally
        {
            SqlDependency.Stop(ConfigurationManager.ConnectionStrings["XXXXX"].ConnectionString);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    相关资源
    最近更新 更多