Why does the SignalR signal change function work many times?

I am trying to develop an asp.net mvc application and also trying to use signalr. The problem is that I have two tables that control user attributes in the project. I have a notification table as well as a NotificationUser table in which there are many notification tables and user tables. I try so that if a user creates a notification to another user in the system, I try to show a pop-up window that confirms the user with a simple message like "Hello! New notification received." The problem is that the javascript function changes the frequency of the signal, so many times. All the steps that I used in the signal below are

stored procedure

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 

Hub

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

Class startup

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

Partial view

  [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); } } } 

Finally, Script

  $(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 so many times if the user creates a notification. What is the problem? Any ideas? I can not optimize it

EDIT 1 I call NtfHub.NotifyChanges in the controller.

  void dependancy_OnChange(object sender, SqlNotificationEventArgs e) { if (e.Type == SqlNotificationType.Change) { NtfHub.NotifyChanges(); } } 
+5
source share
2 answers

Although I believe that SqlDependency is the wrong approach for this function, you can try to solve this specific problem as follows:
Add the "subscribeToNotifications" parameter to your controller action.

 public ActionResult GetNtf(bool subscribeToNotifications) 

Create SqlDependency only if true.
Then subscribe to notifications only when the hub starts (this will prevent the creation of several SqlDependencies for the same user):

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

But keep in mind that updating each page will still create a new listener without server side subscription management.

Option 2 is to create a single SqlDependency (when starting the server) that omits the userId parameter - in any case, you send a notification to all users, regardless of who received the message.

Option 3 - the real solution eliminates SqlDependency in general and sends a notification only to a specific user (message recipient)

0
source

The reason is that you are not unsubscribing from the dependancy_OnChange event, the sqlependency trigger is a one-time execution, so every time it starts, you have to subscribe to a new one, what you do not do is unsubscribe from the previous event, so when you subscribe to a new one, now you have several handlers for the same trigger.

 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(); } 
0
source

All Articles