我有一个将传入数据插入SQL表的推送服务,我需要创建一个应该监听此表的应用程序来查看新的传入数据。
有没有办法收听这个表而不必经常选择数据库进行新的更改?如果对这些数据没有用处,我只是在阅读之后删除该行,还是更好地定期清理?
这是我的实际代码,它没有给我任何关于插入表的通知,我做错了什么?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace Navman_SPI_Service
{
public partial class Service1 : ServiceBase
{
SqlConnection con = new SqlConnection();
String passAvl = Properties.Settings.Default.AVLPass;
String usuarioAvl = Properties.Settings.Default.AVLuser.ToString();
String servidor = Properties.Settings.Default.Server.ToString();
String DataB = Properties.Settings.Default.DB.ToString();
String SQLuser = Properties.Settings.Default.DBuser.ToString();
String SQLpass = Properties.Settings.Default.DBpassword.ToString();
SqlCommand dependencyCommand = new SqlCommand();
String connectionString = "";
public Service1()
{
InitializeComponent();
}
public String getQuery()
{
return "SELECT MessageID FROM dbo.navman_ic_api_message WHERE Proccessed IS NULL";
}
public void OnDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
dependencyCommand.CommandText = getQuery();
connectionString = "Data Source=";
connectionString += servidor + ";Initial Catalog=FOO;Persist Security Info=True;User ID=";
connectionString += SQLuser + ";Password=";
connectionString += SQLpass + ";Initial Catalog=" + DataB;
con = new SqlConnection(connectionString);
try
{
con.Open();
}
catch (Exception f)
{
var logging = new StringBuilder();
var filePath = @"c:\temp\log.txt";
String timestamp = DateTime.Now.ToString("[yyyy:MM:dd][HH:mm:ss]");
logging.Append(timestamp + Environment.NewLine + Environment.NewLine + connectionString + Environment.NewLine + Environment.NewLine + f.ToString() + Environment.NewLine + Environment.NewLine);
File.AppendAllText(filePath, logging.ToString());
}
if (con.State == ConnectionState.Open)
{
Initialization();
dependencyStarter();
var logging = new StringBuilder();
var filePath = @"c:\temp\test.txt";
String timestamp = DateTime.Now.ToString("[yyyy:MM:dd][HH:mm:ss]");
logging.Append(timestamp + Environment.NewLine + Environment.NewLine + "SUCCESS" + Environment.NewLine + Environment.NewLine);
File.AppendAllText(filePath, logging.ToString());
}
}
protected override void OnStop()
{
Termination();
}
void dependencyStarter()
{
// Assume connection is an open SqlConnection.
// Create a new SqlCommand object.
using (SqlCommand command = new SqlCommand(getQuery(),con))
{
// Create a dependency and associate it with the SqlCommand.
SqlDependency dependency = new SqlDependency(dependencyCommand);
// Maintain the refence in a class member.
// Subscribe to the SqlDependency event.
dependency.OnChange += new
OnChangeEventHandler(OnDependencyChange);
// Execute the command.
using (SqlDataReader reader = command.ExecuteReader())
{
// Process the DataReader.
}
}
}
void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
// Handle the event (for example, invalidate this cache entry).
var logging = new StringBuilder();
var filePath = @"c:\temp\test.txt";
String timestamp = DateTime.Now.ToString("[yyyy:MM:dd][HH:mm:ss]");
logging.Append(timestamp + Environment.NewLine + Environment.NewLine + sender.ToString() + Environment.NewLine + Environment.NewLine);
File.AppendAllText(filePath, logging.ToString());
}
void Termination()
{
// Release the dependency.
SqlDependency.Stop(connectionString);
}
void Initialization()
{
// Create a dependency connection.
SqlDependency.Stop(connectionString);
SqlDependency.Start(connectionString);
}
}
}
谢谢,
答案 0 :(得分:4)
尝试使用SqlDependency。 Detecting Changes with SqlDependency
我已在许多项目中使用过这些项目,但它们似乎运作良好。这使用QueryNotifications,它是SQL Server Service Broker的一部分。
如果Broker尚未激活,则必须启用它。让DBA运行以下内容:
USE master;
GO
ALTER DATABASE MyDatabase SET ENABLE_BROKER;
GO
文章中的示例代码:
void Initialization()
{
// Create a dependency connection.
SqlDependency.Start(connectionString, queueName);
}
void SomeMethod()
{
// Assume connection is an open SqlConnection.
// Create a new SqlCommand object.
using (SqlCommand command=new SqlCommand(
"SELECT ShipperID, CompanyName, Phone FROM dbo.Shippers",
connection))
{
// Create a dependency and associate it with the SqlCommand.
SqlDependency dependency=new SqlDependency(command);
// Maintain the refence in a class member.
// Subscribe to the SqlDependency event.
dependency.OnChange+=new
OnChangeEventHandler(OnDependencyChange);
// Execute the command.
using (SqlDataReader reader = command.ExecuteReader())
{
// Process the DataReader.
}
}
}
// Handler method
void OnDependencyChange(object sender,
SqlNotificationEventArgs e )
{
// Handle the event (for example, invalidate this cache entry).
}
void Termination()
{
// Release the dependency.
SqlDependency.Stop(connectionString, queueName);
}
基本上,您在SQL Server中设置一个回调,只要给定查询的结果发生变化,就会调用该回调。然后由你来做点什么。
您可能希望在表格上有一列,以便您可以判断数据是否为新数据。像" CreateDate"或"已处理"。从依赖项查询中排除它。然后你可以在以后使用它来获取新东西。
我应该注意,如果表经常更改,最好定期进行轮询,只需将所有更改作为一个批处理,而不是一次尝试处理它们。 SqlDependency非常适合刷新缓存数据。它不适合处理被用作事务队列的表。
完成后我不会删除数据。只需在下一个查询中忽略它,或者将其移动到存档表。如果您以后需要对其进行故障排除,删除信息通常是一个坏主意。