我尝试开发一个asp.net mvc应用程序,并尝试使用signalr。问题是我有两个表来控制项目中的用户通知。我有一个Notification表和NotificationUser表,它是多对多的通知和用户表。我正在尝试,如果用户在系统中向另一个用户创建通知,我会尝试显示一个弹出窗口,用一个简单的消息来确认用户,例如'嘿!收到新通知'。问题是信号器的javascript更改功能击中了这么多次。我在下面列出的signalR中使用的所有步骤
存储过程
ALTER PROCEDURE [dbo].[GetNotifications]
@userid int
AS
BEGIN
select n.Ntf_Title,Ntf_Description,n.Ntf_Date from dbo.SysNotifications n INNER JOIN dbo.SysNotificationUser u on n.Ntf_ID =u.NtU_NtfID where NtU_UserID=@userid AND NtU_IsRead=0
END
The Hub
[HubName("signalRHub")]
public class NtfHub : Hub
{
[HubMethodName("notifyChanges")]
public static void NotifyChanges()
{
var context = GlobalHost.ConnectionManager.GetHubContext<NtfHub>();
context.Clients.All.notifyChanges();
}
}
StartUp Class
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
部分视图
[HttpGet]
public ActionResult GetNtf()
{
//NtfRepo rp = new NtfRepo(this.HttpContext);
string connectionString = ConfigurationManager.ConnectionStrings["conn"].ConnectionString;
int userid =id;
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
using (SqlCommand sqlcom = new SqlCommand("[GetNotifications]", sqlcon))
{
sqlcon.Open();
sqlcom.CommandType = CommandType.StoredProcedure;
sqlcom.Parameters.AddWithValue("@userid", userid);
sqlcom.Notification = null;
SqlDependency dependancy = new SqlDependency(sqlcom);
dependancy.OnChange += dependancy_OnChange;
var reader = sqlcom.ExecuteReader();
var ntf= reader.Cast<IDataRecord>()
.Select(e => new PopulateNtfBar()
{
Title = e.GetString(0),
Description = e.GetString(1),
TimeDiff = FindDifferenceTime(e.GetDateTime(2))
}).ToList();
return PartialView("~/Views/Shared/CheckNotification.cshtml", ntf);
}
}
}
最后,剧本
$(function () {
var notification = $.connection.signalRHub;
// Create a function that the hub can call to broadcast messages.
notification.client.notifyChanges = function () {
getData();
toastr.warning("Hey,You have Ntf");
};
// Start the connection.
$.connection.hub.start().done(function () {
getData();
}).fail(function (e) {
});
});
function getData() {
var tbl = $("#header_notification_bar")
$.ajax({
url: '@Url.Action("GetNtf","Home")',
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
tbl.empty().append(result);
}).error(function () {
});
}
如果用户创建通知,notification.client.notifyChanges会多次击中。问题出在哪里?任何的想法?我无法优化它
编辑1 我在控制器中调用NtfHub.NotifyChanges。
void dependancy_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
NtfHub.NotifyChanges();
}
}
答案 0 :(得分:0)
虽然我认为SqlDependency对于此功能是错误的方法,但您可以尝试以这种方式解决此特定问题:
将参数“subscribeToNotifications”添加到控制器操作
public ActionResult GetNtf(bool subscribeToNotifications)
仅当它为True时才创建SqlDependency 然后在hub启动时订阅 only 上的通知(这将阻止为同一用户创建多个SqlDependencies):
$(function () {
var notification = $.connection.signalRHub;
// Create a function that the hub can call to broadcast messages.
notification.client.notifyChanges = function () {
getData(false);
toastr.warning("Hey,You have Ntf");
};
// Start the connection.
$.connection.hub.start().done(function () {
getData(true);
}).fail(function (e) {
});
});
function getData(subscribeToNotifications) {
var tbl = $("#header_notification_bar")
$.ajax({
url: '@Url.Action("GetNtf","Home")' + '?subscribeToNotifications=' + subscribeToNotifications,
contentType: 'application/html ; charset:utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
tbl.empty().append(result);
}).error(function () {
});
}
但请注意,每次页面刷新仍会创建新的侦听器,而无需管理服务器端的订阅。
选项2 是创建单个SqlDependency(在服务器应用启动时)省略userId参数 - 无论如何,无论哪个用户收到消息,您都会向所有用户发送通知。
选项3 - 真正的解决方案是完全摆脱SqlDependency并向特定用户(消息的收件人)发送仅通知
答案 1 :(得分:0)
原因是你没有取消订阅dependancy_OnChange事件,sqldependency触发器是一次性执行,所以你必须在每次触发时订阅新的,你不做的是取消订阅前一个事件处理程序,因此当您订阅新的处理程序时,您现在有多个处理程序用于同一个触发器。
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dependency = sender as SqlDependency;
if (dependency != null) dependency.OnChange -= dependency_OnChange;
//Recall your SQLDependency setup method here.
SetupDependency();
}