这是我第一次需要使用SqlDependency,所以我希望它是我犯的一个愚蠢的错误。
我遇到的问题是,当SQL表更改时,不会触发OnChanged事件。没有错误或其他任何东西不会触发。
这是代码
public class SqlWatcher { private const string SqlConnectionString = "Data Source = CN-PC08\\DEV; Initial Catalog=DEP; User = sa; Password=******"; public SqlWatcher() { SqlClientPermission perm = new SqlClientPermission(System.Security.Permissions.PermissionState.Unrestricted); perm.Demand(); SqlCommand cmd = new SqlCommand("SELECT [DataAvaliable], [RowNumber] FROM [dbo].[Trigger]", new SqlConnection(SqlConnectionString)); SqlDependency sqlDependency = new SqlDependency(cmd); sqlDependency.OnChange += On_SqlBitChanged; } private void On_SqlBitChanged(object sender, SqlNotificationEventArgs sqlNotificationEventArgs) { SqlDependency dependency = (SqlDependency)sender; dependency.OnChange -= On_SqlBitChanged; // Fire the event if (NewMessage != null) { NewMessage(this, new EventArgs()); } } public void Start() { SqlDependency.Start(SqlConnectionString); } public void Stop() { SqlDependency.Stop(SqlConnectionString); } public event EventHandler NewMessage;
在我的主窗口中
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); try { SqlWatcher sqlWatcher = new SqlWatcher(); sqlWatcher.Start(); sqlWatcher.NewMessage += On_NewMessage; } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void On_NewMessage(object sender, EventArgs eventArgs) { MessageBox.Show("Message Received"); } }
因此,预期的行为是,如果我运行以下sqlQuery,将显示一个messageBox,显示“收到消息”
INSERT INTO [DEP].[dbo].[Trigger] Values(0,3)
谁能给我提示要检查/更改的内容吗?
我知道在依赖项中只能使用Sql功能的一个子集,但是我不认为我想在这里做任何事情。
我希望这是我犯的一个愚蠢的错误。
不幸的是(或者幸运的是?)您犯了几个错误。
首先,您需要了解查询通知将使 一个查询 无效。因此,您最多只会收到 一次 通知,如果您想接收更多通知,则必须重新订阅(重新提交查询)。
接下来,您需要了解,由于 任何 原因,您不仅会收到更改通知,还会收到通知。在回调中,您 必须 检查通过传入的通知原因SqlNotificationEventArgs。
SqlNotificationEventArgs
接下来,您需要了解异步编程的基本原理:如果订阅事件,请确保在事件第一次发生 之前* 就进行订阅。恰当的例子: 您提交查询后,便会立即On_SqlBitChanged触发。这 应该 在构造函数中发生,但是您可以 在 构造函数运行 后 订阅。在挂接事件回调之前,可以在构造函数完成之间调用它,在这种情况下,该通知将被静默忽略。 * SqlWatcher.SqlWatcher``sqlWatcher.NewMessage On_SqlBitChanged``NewMessage
On_SqlBitChanged
SqlWatcher.SqlWatcher``sqlWatcher.NewMessage
On_SqlBitChanged``NewMessage
如果要使用服务,请确保 在 使用 前 将其启动。您在中使用SqlDependency,SqlWatcher.SqlWatcher但 随后 在调用时启动它SqlWatcher.Start()。
SqlWatcher.SqlWatcher
SqlWatcher.Start()
最后,如果您希望收到有关查询更改的通知, 则必须提交查询 。您正在构造SqlCommand对象,设置通知,然后…丢弃对象。除非您实际提交查询,否则您还没有预订 任何东西 。
SqlCommand
修复建议:
Start
Stop
NewMessage
SqlComamnd.ExecuteQuery()
Info
Type
Source
还有一件事:不要在后台回调中调用UI代码。您不能MessageBox.Show("Message Received");从回调中调用,必须通过路由通过表单主线程Form.Invoke。是的,我知道严格来说,MessageBox.Show它确实 适用于非UI线程,但是您很快就会离开警报框而真正形成交互作用,然后一切都会中断。
MessageBox.Show("Message Received");
Form.Invoke
MessageBox.Show