-->

signalr with sqldepdency firing multiple times for

2019-09-14 19:01发布

问题:

I am having a asp.net mvc app with vs2013 and .net framwork 4.5.1 which should notify users when a certain field gets updated and for a certain recordID. Everything works fine when I have a single instance of the browser open, but when i open another tab or browser either on the same machine or on the different machine it fires the sqldepdencychange event multiple times.

Below is my hub code

public class MessagesHub : Hub
    {
        private static string conString = ConfigurationManager.ConnectionStrings["FleetLink_DB"].ToString();

        private static string hostName = "";


        public static void SendMessages(string hName)
        {
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessagesHub>();
            hostName = hName;
            context.Clients.Group(hostName).updateMessages(hName);
        }

        public Task leaveGroup(string hName)
        {
            return Groups.Remove(Context.ConnectionId, hName);
        }

        public Task joinGroup(string hName)
        {
            return Groups.Add(Context.ConnectionId, hName);
        }
}

Below is my signalr script file

  $(function () {
            var dialog, form
            // Declare a proxy to reference the hub.

            var notifications = $.connection.messagesHub;
            //debugger;
            //Create a function that the hub can call to broadcast messages.
            notifications.client.updateMessages = function (hName) {
                alert("testing");
                getoneMessages(hName)
            };

            $.connection.hub.logging = true;
            $.connection.hub.start().done(function () {
                var hostName = getUrlVars()["System_Name"];
                notifications.server.joinGroup(hostName);
            }).fail(function (e) {
                alert(e);
            });
        });

        function getUrlVars() {
            var vars = [], hash;
            var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
            for (var i = 0; i < hashes.length; i++) {
                hash = hashes[i].split('=');
                vars.push(hash[0]);
                vars[hash[0]] = hash[1];
            }
            return vars;
        }

        function getoneMessages(hName) {
            var tbl = $('#selectable');
            //alert('mesgID=' + mesgID)
            //var tbl = $('#selectable');
            $.ajax({
                url: '/controller/view',
                cache: false,
                contentType: 'application/html ; charset:utf-8',
                type: 'GET',
                dataType: 'html'
            }).success(function (result) {
                //alert(result);
                tbl.empty().append(result);
            }).error(function (exception) {
                //alert('failed= ' + exception);
            });
        }

        window.onbeforeunload = function (e) {
            var hostName = getUrlVars()["System_Name"];
            notifications.server.joinGroup(hostName);
            $.connection.hub.stop();

        };

Below is my partialview code along with the definition for RegisterForNotification and depdendency_onchange event

public PartialViewResult SignalRTesterPartialView()
{
 /...COde not included for brevity..../
   RegisterForNotifications(ID);
}



public void RegisterForNotifications(int mID)
        {
            var efConnectionString = ConfigurationManager.ConnectionStrings["DB"].ConnectionString;
            var builder = new EntityConnectionStringBuilder(efConnectionString);
            var regularConnectionString = builder.ProviderConnectionString;

            string commandText = null;


            commandText = "select ID,Status,Name from tblABC where ID=" + strID;

                using (SqlConnection connection = new SqlConnection(regularConnectionString))
                {
                    using (SqlCommand command = new SqlCommand(commandText, connection))
                    {
                        connection.Open();

                        var dependency = new SqlDependency(command);
                        dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);

                        // NOTE: You have to execute the command, or the notification will never fire.
                        var reader = command.ExecuteReader();
                    }
                }

        }

        private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
        {
            if (e.Type == SqlNotificationType.Change && e.Info== SqlNotificationInfo.Update)
            {
                MessagesHub.SendMessages(hName);
            }

            RegisterForNotifications(1012);


        }

Not sure why it is firing the sendmessages multiple times with each additional browser instance that I open. Any pointers would be helpful!

回答1:

remove EventHandler when you done with it

private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
    if (e.Type == SqlNotificationType.Change && e.Info== SqlNotificationInfo.Update)
    {
        MessagesHub.SendMessages(hName);
    }

    //remove event handler
    SqlDependency dependency = sender as SqlDependency;
    dependency.OnChange -= new OnChangeEventHandler(dependency_OnChange);

    RegisterForNotifications(1012);
}