为什么SignalR改变功能多次击中?

may*_*ayk 5 c# asp.net-mvc sqldependency signalr

我尝试开发一个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
Run Code Online (Sandbox Code Playgroud)

枢纽

 [HubName("signalRHub")]
 public class NtfHub : Hub
 {
    [HubMethodName("notifyChanges")]
    public static void NotifyChanges()
    {
        var context = GlobalHost.ConnectionManager.GetHubContext<NtfHub>();
        context.Clients.All.notifyChanges();
    }


}
Run Code Online (Sandbox Code Playgroud)

StartUp类

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

    }
}
Run Code Online (Sandbox Code Playgroud)

部分视图

 [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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

最后,剧本

  $(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 () {

        });


    }
Run Code Online (Sandbox Code Playgroud)

如果用户创建通知,notification.client.notifyChanges会多次击中.问题出在哪里?任何的想法?我不能优化它

编辑1我在控制器中调用NtfHub.NotifyChanges.

  void dependancy_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
        {
            NtfHub.NotifyChanges();
        }
    }
Run Code Online (Sandbox Code Playgroud)

Ale*_* L. 0

虽然我认为 SqlDependency 对于此功能来说是错误的方法,但您可以尝试通过以下方式解决此特定问题:
将参数“subscribeToNotifications”添加到控制器操作中

public ActionResult GetNtf(bool subscribeToNotifications)
Run Code Online (Sandbox Code Playgroud)

仅当 SqlDependency 为 True 时才创建。然后仅
在集线器启动时 订阅通知(这将防止为同一用户创建多个 SqlDependency):

$(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 () {

    });
}
Run Code Online (Sandbox Code Playgroud)

但请注意,每次页面刷新仍会创建新的侦听器,而无需在服务器端管理订阅。

选项 2是创建单个 SqlDependency(在服务器应用程序启动时),省略 userId 参数 - 无论如何,无论哪一个用户收到消息,您都会向所有用户发送通知。

选项 3 - 真正的解决方案是完全摆脱 SqlDependency 并向特定用户(消息的收件人)发送通知