【问题标题】:Cannot receive change notifications using SqlDependency [duplicate]无法使用 SqlDependency 接收更改通知 [重复]
【发布时间】:2017-07-30 09:17:44
【问题描述】:

我第一次使用 Sql Server Service Broker,尝试在特定表发生更改时订阅通知。当我调用command.ExecuteReader() 时出现以下异常:

System.InvalidOperationException :在不提供选项值的情况下使用 SqlDependency 时,必须在执行添加到 SqlDependency 实例的命令之前调用 SqlDependency.Start()。

我创建了一个测试来重现该场景(为简洁起见,省略了一些相关方法),如下所示:

private string _queueName = "EventsToPublishChangeMessages";
    private bool _notificationReceived;

    [Test]
    public void WhyDoesExceptionIndcateSqlDependencyStartHasNotBeenCalledPriorToCommandExecuteReader()
    {
        Console.WriteLine($"canRequestNotifications: {CanRequestNotifications()}"); // returns true
        var connectionString = GetConnectionString();
        var started = SqlDependency.Start(connectionString, _queueName); // exception below seems to suggest that I haven't started the SqlDependency. Am I doing something wrong on this line?
        Console.WriteLine($"Started:{started}"); // returns true
        var connection = new SqlConnection(connectionString);
        var command = new SqlCommand("SELECT Id, EventType, [Data], Created FROM dbo.EventsToPublish", connection);
        var sqlDependency = new SqlDependency(command);
        sqlDependency.OnChange += OnChange;
        connection.Open();

        // The following line causes the exception:
        // System.InvalidOperationException : When using SqlDependency without providing an options value, SqlDependency.Start() must be called prior to execution of a command added to the SqlDependency instance.
        // But you can see that I *did* call SqlDependency.Start() above.
        using (var reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                Process(reader);
            }
        }

        TryToTriggerANotification(connectionString);
        Thread.Sleep(5000); // ie. wait a few seconds to ensure notification-handling background thread has had a chance to complete.

        Assert.That(_notificationReceived, Is.True);
    }

    private void TryToTriggerANotification(string connectionString)
    {
        using (var connection = new SqlConnection(connectionString))
        {
            using (var command = new SqlCommand(
                    "INSERT INTO dbo.EventsToPublish(Id, EventType, [Data], Created) VALUES(newid(), 'StackOverflowQuestionTest', '', GETDATE())",
                    connection))
            {
                connection.Open();
                command.ExecuteNonQuery();
            }
        }
    }

    private void OnChange(object sender, SqlNotificationEventArgs e)
    {
        _notificationReceived = true;
    }

    private bool CanRequestNotifications()
    {
        try
        {
            var sqlClientPermission = new SqlClientPermission(PermissionState.Unrestricted);
            sqlClientPermission.Demand();
            return true;
        }
        catch
        {
            return false;
        }
    }

我发出了以下 SQL 查询,试图更好地了解正在发生的事情:

select * from sys.service_queues -- can see my EventsToPublishChangeMessages queue
select is_broker_enabled from sys.databases where database_id=db_id() -- returns 1
select * from sys.dm_qn_subscriptions -- returns nothing
select * from sys.transmission_queue -- returns nothing

有没有人知道我可能做错了什么?

【问题讨论】:

标签: c# service-broker sqldependency


【解决方案1】:

错误信息说:

必须在执行添加到 SqlDependency 实例的命令之前调用SqlDependency.Start()

SqlDependency.Start 上的帮助说明:

启动侦听器以接收依赖项更改通知。

...

确保每个 AppDomain 只调用一次 Start

因此,请在您的应用启动中的某处拨打Start() 电话。由于这看起来像一个测试方法,可能是在 [ClassInitialize] 装饰方法中。

【讨论】:

  • 还有比这更多的东西,但问题的一部分肯定是我每个 AppDomain 不止一次调用 SqlDependency.Start() - 在我原来的情况下,我有两个测试调用包含 SqlDependency.Start() 调用的同一被测系统。对于上面编写的示例测试,我还必须使用带有选项和超时的构造函数重载,并指定“SERVICE=[my-service-name]”选项来解决此问题。
  • @remus 小问题:SqlDependency.Start() 在 AppDomain 启动时调用。在 SqlDependency.Start() 之前调用 SqlDependency.Stop() 有意义吗?
  • @Natalya 请单独提问
  • @RemusRusanu 你能回答这个stackoverflow.com/questions/45478012/…
猜你喜欢
  • 2023-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多