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

SignalR实现SQL数据实时广播问题:仅页面加载时生效

问题修复:数据库变更时SignalR实时推送通知

问题分析

当前代码仅在页面加载时触发一次数据查询和通知,数据库后续变更无法触发推送,核心原因包括:

  1. SqlDependency触发变更后会自动失效,未重新创建新的依赖订阅
  2. 数据库查询逻辑存在潜在风险(如未判断数据读取结果、连接管理不严谨)
  3. 未处理SignalR连接断开后的重连场景

修复步骤及代码调整

1. 调整Hub文件(NotificationHub.cs)

namespace SignalR
{
    [HubName("notificationHub")]
    public class NotificationHub : Hub
    {
        [HubMethodName("sendNotifications")]
        public void SendNotifications()
        {
            string namePrint = string.Empty;
            string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

            using (var connection = new SqlConnection(connectionString))
            {
                string query = "select Name_print from Print_Name_Machine where User_ID = '123'";
                connection.Open();

                using (SqlCommand command = new SqlCommand(query, connection))
                {
                    // 重置通知配置,确保每次创建新的SqlDependency
                    command.Notification = null;
                    SqlDependency dependency = new SqlDependency(command);
                    dependency.OnChange += Dependency_OnChange;

                    using (SqlDataReader dr = command.ExecuteReader())
                    {
                        // 读取数据前先判断是否有有效结果
                        if (dr.HasRows && dr.Read())
                        {
                            namePrint = dr["Name_print"].ToString();
                        }
                    }
                }
            }

            // 获取Hub上下文并推送最新数据到所有客户端
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
            context.Clients.All.recieveNotification(namePrint);
        }

        private void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
        {
            // 仅处理合法的变更事件,排除无效通知
            if (e.Type == SqlNotificationType.Change && e.Info != SqlNotificationInfo.Invalid)
            {
                // 重新订阅依赖并推送最新数据
                SendNotifications();
                // 移除旧的事件绑定,避免内存泄漏
                ((SqlDependency)sender).OnChange -= Dependency_OnChange;
            }
        }
    }
}

2. 启用SQL Server Service Broker

SqlDependency依赖SQL Server的Service Broker功能,需执行以下SQL命令启用:

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

3. 客户端代码优化(Index.cshtml)

添加连接重连逻辑,确保客户端断开后自动恢复连接:

@*@{
    ViewBag.Title = "Home Page";
}*@

<div class="row">
    <h1>Broadcast Realtime SQL data using SignalR</h1>
    <div>
        <p>You have <span id="spanNewMessages">0</span> New Message Notification.</p>
    </div>
</div>

@section scripts {
    <script src="~/Scripts/jquery.signalR-2.4.3.js"></script>
    <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            var notifications = $.connection.notificationHub;

            // 接收服务器推送的最新数据
            notifications.client.recieveNotification = function (totalNewMessages) {
                $('#spanNewMessages').text(totalNewMessages || 0);
            };

            // 定义连接启动逻辑,用于初始化和重连
            function startConnection() {
                $.connection.hub.start()
                    .done(function () {
                        console.log("SignalR连接成功");
                        // 连接成功后立即请求最新数据
                        notifications.server.sendNotifications();
                    })
                    .fail(function (e) {
                        console.error("连接失败:", e);
                        // 连接失败后5秒重试
                        setTimeout(startConnection, 5000);
                    });
            }

            // 监听连接断开事件,自动触发重连
            $.connection.hub.disconnected(function () {
                setTimeout(startConnection, 5000);
            });

            // 初始化连接
            startConnection();
        });
    </script>
}

4. Startup.cs保持现有配置(无需修改)

[assembly: OwinStartup(typeof(SignalR.Startup))]

namespace SignalR
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

关键修复点说明

  • 持续订阅SqlDependency:每次调用SendNotifications时创建新的依赖实例,确保数据库变更能持续触发通知
  • 数据读取安全:添加dr.HasRows判断,避免空引用异常
  • 内存泄漏防护:触发变更后移除旧的事件绑定,防止资源占用
  • 客户端重连机制:连接断开后自动重试,保障实时推送的稳定性
  • Service Broker启用:必须在SQL Server中启用该功能,否则SqlDependency无法正常工作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:00:34