You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SqlDependency在MVVM中异常:已调用Start仍报错求助

解决SqlDependency的启动异常问题

你虽然调用了SqlDependency.Start(),但时机和使用方式上有几个关键问题,导致异常依然出现,我来帮你拆解一下:

1. SqlDependency.Start()的调用时机错误

你当前的代码是先打开数据库连接,再调用Start(),但SqlDependency.Start()需要在任何数据库连接打开之前执行。因为这个方法要初始化SQL Server的Service Broker监听机制,包括创建内部消息队列和关联会话。如果连接已经打开,Start的初始化无法关联到这个已打开的连接上,自然会触发"未调用Start()"的异常。

2. 不要重复调用Start()

SqlDependency.Start()是应用级别的初始化操作,只需要调用一次(比如在WPF应用的启动事件里,或者ASP.NET的Global.asax中),而不是每次执行数据库操作都调用。多次调用虽然不会直接报错,但会浪费资源,还可能导致监听状态混乱。

3. 检查SQL命令的格式要求

SqlDependency对SQL语句有严格限制,你的SELECT count(*) from users需要调整一点:

  • 必须指定表的架构名(比如dbo.users,如果你的表在其他架构下就换成对应的),避免SQL Server无法识别监听的目标表。

4. 确保连接字符串一致

调用SqlDependency.Start()时用的连接字符串,必须和你打开数据库连接时用的完全一致,否则监听机制无法关联到对应的连接会话。


修正后的代码示例

首先,在应用启动时调用一次Start()(以WPF的App.xaml.cs为例):

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    // 仅在应用启动时调用一次
    string connStr = ConfigurationManager.ConnectionStrings["StringConnexion"].ConnectionString;
    SqlDependency.Start(connStr);
}

protected override void OnExit(ExitEventArgs e)
{
    base.OnExit(e);
    // 应用退出时停止监听,释放资源
    string connStr = ConfigurationManager.ConnectionStrings["StringConnexion"].ConnectionString;
    SqlDependency.Stop(connStr);
}

然后修改你的业务方法:

public void something()
{
    string connStr = ConfigurationManager.ConnectionStrings["StringConnexion"].ConnectionString;
    using (SqlConnection connection = new SqlConnection(connStr))
    {
        connection.Open();
        
        using (SqlCommand command = new SqlCommand("SELECT count(*) FROM dbo.users", connection))
        {
            // 重置命令的通知属性,确保订阅能正常生效
            command.Notification = null;
            
            SqlDependency dependency = new SqlDependency(command);
            dependency.OnChange += OnDependencyChange;
            
            using (SqlDataReader reader = command.ExecuteReader())
            {
                if (reader.Read())
                {
                    var userCount = reader.GetInt32(0);
                    MessageBox.Show(userCount.ToString());
                    UserCount = userCount.ToString();
                }
            }
        }
    }
}

private void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
    // 处理数据变更逻辑,注意要重新订阅下一次监听
    SqlDependency dependency = sender as SqlDependency;
    dependency.OnChange -= OnDependencyChange;
    
    // 重新执行查询并订阅,保证持续监听
    something();
}

另外还要确保你的SQL Server已经启用了Service Broker,可以用这个SQL命令检查:

SELECT name, is_broker_enabled FROM sys.databases WHERE name = '你的数据库名';

如果is_broker_enabled的值是0,执行下面的命令启用:

ALTER DATABASE 你的数据库名 SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE;

内容的提问来源于stack exchange,提问作者Black Panther

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:59:53