保持C#应用程序打开并检查数据库
我有这个应用程序。与一个数据库连接并向android设备发送通知。我想保持此应用程序始终打开,并检查数据库中的新记录。我唯一的想法是放入一个无限循环,如while(true),但我在connection.Open()行中有警告关于内存,程序正在停止保持C#应用程序打开并检查数据库,c#,sql-server,infinite-loop,C#,Sql Server,Infinite Loop,我有这个应用程序。与一个数据库连接并向android设备发送通知。我想保持此应用程序始终打开,并检查数据库中的新记录。我唯一的想法是放入一个无限循环,如while(true),但我在connection.Open()行中有警告关于内存,程序正在停止 namespace AndroidParse { class Program { static void Main(string[] args) { //SqlDataReader reader; S
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();
}
}
}
使用Denis Reznik建议的
SqlDependency
对象是一个很好的解决方案。
需要记住的几件事:
SqlDependency
要求SQL Server Service Broker服务在SQL Server上运行(此处有更多详细信息:)SqlCommand
中使用的查询基本上是在服务器上连续执行的。。。因此,查询的功能有一些限制(例如,没有聚合)。更多详情请参见Smudge202的SO答案:SqlDependency
来简单地通知更改,然后通过调用数据访问方法等来执行更改。。。比尝试实际使用查询检索数据更容易。因此,在您的示例中,您可能希望让SqlDependency
通知有更改,然后创建一个单独的数据访问方法/sp/etc。。。检索设备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);
}
}
}
计时器可能更合适。您也可以将其包装到windows服务中。如果您具有对数据库的写入权限,只需在更新或插入时设置触发器,并让它执行此脚本即可。否则,是的,计时器可能是最好的。计时器成就了我的一天。谢谢大家。请记住,如果您使用的是计时器(而不是DB触发器),如果在timer.tick事件中进行了多个更新,那么您将只对最近的一个进行操作,因为您只选择了“前1个”