SignalR SqlDependency Update 工作,但在更改页面时停止工作

本文关键字:停止工作 Update SqlDependency 工作 SignalR | 更新日期: 2024-11-08 15:07:29

您好,感谢您阅读本文。

使用本指南作为我的基础,我只添加了 Owin 登录/注册(cookie)

当我登录时,它会显示来自我的通知中心的通知,并且我能够更新数据库并立即运行更新。因此,在您尝试切换页面之前,一切正常,然后通知停止。即使我只是更新当前页面。

可能是什么问题?

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System.Security.Claims;
using System.Collections.Concurrent;
namespace LifeChange
{
[HubName("notificationHub")]
public class NotificationHub : Hub
{
    private static readonly ConcurrentDictionary<string, User> Users = new ConcurrentDictionary<string, User>(StringComparer.InvariantCultureIgnoreCase);
    private static List<User> UserList = new List<User>();
    Int16 totalNewMessages = 0;
    string UserID;
    [HubMethodName("check")]
    public Task Check(string id)
    {
        if (!Users.ToList().Exists(i => i.Value.ProfileId == id))
        {
            string profileId = id; //Context.QueryString["id"];
            string connectionId = Context.ConnectionId;
            var user = Users.GetOrAdd(profileId, _ => new User
            {
                ProfileId = profileId,
                ConnectionIds = connectionId
            });
            lock (user.ConnectionIds)
            {
                Groups.Add(connectionId, user.ProfileId);
            }
            return base.OnConnected();
        }
        return null;
    }
    [HubMethodName("sendNotifications")]
    public Task SendNotifications(string id)
    {
        UserID = id;
        using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
        {
            string query = "SELECT NotificationNumber FROM [dbo].[NotificationStatus] WHERE UserID=" + UserID;
            connection.Open();
            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Notification = null;
                DataTable dt = new DataTable();
                SqlDependency dependency = new SqlDependency(command);
                dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
                if (connection.State == ConnectionState.Closed)
                    connection.Open();
                var reader = command.ExecuteReader();
                dt.Load(reader);
                if (dt.Rows.Count > 0)
                {
                    totalNewMessages = Int16.Parse(dt.Rows[0]["NotificationNumber"].ToString());
                }
            }
        }
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
        //return context.Clients.All.RecieveNotification(totalNewMessages);
        return context.Clients.Client(Users.Values.FirstOrDefault(i => i.ProfileId == UserID).ConnectionIds).RecieveNotification(totalNewMessages);
    }
    private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
        {
            NotificationHub nHub = new NotificationHub();
            nHub.SendNotifications(UserID);
        }
    }
}
}

SignalR SqlDependency Update 工作,但在更改页面时停止工作

这里有很多错误,你应该先阅读一些关于 SignalR 概念的好的基本文档。您所指的指南非常差。您应该检查的主要事项:

  • 每次从客户端调用中心方法时,SignalR 都会从头开始创建集线器,然后销毁,因此对于像这样基本的事情,您不应该干扰它,而是使用事件处理程序
  • 由于上一点,您的UserID成员根本不在正确的位置,它对您有用,只是因为您正在产生错误的副作用,并产生更多错误(如下所述): 不要在集线器实例成员中存储任何应该跨调用存在的状态,它并不意味着生存
  • 你显式地对与 SignalR 广播无关的事情执行new NotificationHub(),你应该将 sql 依赖项的东西移到中心之外并在那里做,而让中心只做自己的事情
  • 当您更改页面时,您的连接会丢失,购买您的事件处理程序(可能)人为地使"死"中心实例保持活动状态,并且它使用它进行通知,但这完全是错误的

应查看设计,首先在中心外部管理 SQL 依赖项。您已经知道 IHubContext ,因此请从外部集线器使用它,并且您应该仅将集线器用于它们的用途,而不是在将它们附加到依赖事件时人为地保持活动状态,或者更糟糕的是,显式创建它们。你正走在纠缠不清的意大利面条代码的路上,这很难推理和理解,因为你显然正在经历。