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 概念的好的基本文档。您所指的指南非常差。您应该检查的主要事项:
- 每次从客户端调用中心方法时,SignalR 都会从头开始创建集线器,然后销毁,因此对于像这样基本的事情,您不应该干扰它,而是使用事件处理程序
- 由于上一点,您的
UserID
成员根本不在正确的位置,它对您有用,只是因为您正在产生错误的副作用,并产生更多错误(如下所述): 不要在集线器实例成员中存储任何应该跨调用存在的状态,它并不意味着生存 - 你显式地对与 SignalR 广播无关的事情执行
new NotificationHub()
,你应该将 sql 依赖项的东西移到中心之外并在那里做,而让中心只做自己的事情 - 当您更改页面时,您的连接会丢失,购买您的事件处理程序(可能)人为地使"死"中心实例保持活动状态,并且它使用它进行通知,但这完全是错误的
应查看设计,首先在中心外部管理 SQL 依赖项。您已经知道 IHubContext
,因此请从外部集线器使用它,并且您应该仅将集线器用于它们的用途,而不是在将它们附加到依赖事件时人为地保持活动状态,或者更糟糕的是,显式创建它们。你正走在纠缠不清的意大利面条代码的路上,这很难推理和理解,因为你显然正在经历。