首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SqlDependency OnChange未触发

SqlDependency OnChange未触发
EN

Stack Overflow用户
提问于 2013-03-22 17:35:57
回答 1查看 17.2K关注 0票数 5

这是我第一次需要使用SqlDependency,所以我希望这是我犯的一个愚蠢的错误。

我遇到的问题是,当sql表发生变化时,OnChanged事件不会触发。没有错误或任何东西,只是它不会触发。

以下是代码

代码语言:javascript
复制
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;

在我的主窗口中,我有这个

代码语言:javascript
复制
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,显示"Message Received“

代码语言:javascript
复制
INSERT INTO [DEP].[dbo].[Trigger] Values(0,3)

有没有人能给我一个提示,告诉我应该检查/更改什么?

我知道在依赖中只能使用Sql特性的一个子集,但我不认为我在这里做任何花哨的事情。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-22 18:03:55

,我希望这是我犯的一个愚蠢的错误。

不幸的(或幸运的?)你犯了几个错误。

首先,您需要了解查询通知将使one query失效。因此,您最多只会收到一次通知,并且您必须再次订阅(重新提交查询)如果您想收到更多notifications.

  • Next,您需要了解,无论出于何种原因,您都会收到通知,而不仅仅是更改。在您的回调中,您必须检查通知您的原因,这些原因是通过SqlNotificationEventArgs传入的。

  • 接下来,您需要了解异步编程的基本原则:如果您订阅了一个事件,请确保您在订阅之前订阅了,该事件可以第一次发生。例如:只要您提交查询,On_SqlBitChanged就可以触发。这应该发生在SqlWatcher.SqlWatcher构造函数中,但是您需要在构造函数运行之后订阅sqlWatcher.NewMessage。在连接NewMessage事件回调之前,可以在构造函数完成之间调用On_SqlBitChanged,在这种情况下,通知将被静默忽略。

  • 如果要使用服务,请确保在使用之前先启动它。您在SqlWatcher.SqlWatcher中使用SqlDependency,但在此之后调用SqlWatcher.Start()时会启动它。

  • 最后,如果您希望在查询发生更改时收到通知,则必须提交查询。您正在构造SqlCommand对象,设置通知,然后...丢弃该对象。除非您实际提交了查询,否则您尚未订阅任何内容。

修复建议:

  • 进行StartStop统计,在应用程序启动时调用Start

  • 确保您在提交NewMessage之前订阅了Info提交查询(call SqlComamnd.ExecuteQuery())

  • Inspect Stop InfoTypeSourceOn_SqlBitChanged回调中,如果您的提交包含错误,这是学习的唯一途径( SqlComamnd.ExecuteQuery()将成功,即使通知请求无效)

  • 当您收到更改通知时,必须重新订阅。再次执行查询。

还有一件事:不要在后台回调中调用UI代码。不能从回调调用MessageBox.Show("Message Received");,必须通过Form.Invoke通过窗体主线程进行路由。是的,我知道严格地说,MessageBox.Show确实在非UI线程上工作,但你很快就会从警告框转移到实际的交互中,然后事情就会崩溃。

票数 22
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15566966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档