SignalR duplicate messages on sqlDependency change SignalR duplicate messages on sqlDependency change angularjs angularjs

SignalR duplicate messages on sqlDependency change


As far as I can see, your code has a couple of problems:

  • Every time when your client connects to the server it invokesSignalRGetData. According to your code SigalRGetData creates anew SqlDependency entity. Thus, if you have two clients you willhave two SqlDependency entities or two database subscriptions whichmeans you will have two notifications on the side of each client. If you want to send one notification for each client when a change in the database occurs you should have just only one SqlDependency entity for your application.
  • According to your code you will have a notification just only for the first database change (I know it is strange, but it is true). If you want to receive notifications continuously you should make resubscribtion:

The MSDN contains a sample of how to use the SqlDependency here. Note how, similarly to the SqlNotification usage, the client is expected to subscribe again if it whishes to be further notified

  • SqlDependency has the problems with memory leaks. Hovewer, you can use an open source realization of the SqlDependency class - SqlDependencyEx. It uses a database trigger and native Service Broker notification to receive events about the table changes. With SqlDependecyEx you are able to monitor INSERT, DELETE, UPDATE separately and receive actual changed data (xml) in the event args object. This is an usage example:
int changesReceived = 0;using (SqlDependencyEx sqlDependency = new SqlDependencyEx(          TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) {    sqlDependency.TableChanged += (o, e) => changesReceived++;    sqlDependency.Start();    // Make table changes.    MakeTableInsertDeleteChanges(changesCount);    // Wait a little bit to receive all changes.    Thread.Sleep(1000);}Assert.AreEqual(changesCount, changesReceived);

Suggestion:

To avoid duplicated client-side notifications it is better to use one notification exemplar for your controller/application. A code example from my last project:

public class HomeController : Controller{    // One global subscription for all the controller.    static HomeController()    {        // ITableRowRepository incapsulates SqlDependencyEx usage.        var repo = (ITableRowRepository)DependencyResolver.Current                           .GetService(typeof(ITableRowRepository));        // One global subscription.        repo.TableChanged += RepoTableChanged;    }    // Actions here.    private static void RepoTableChanged(object sender, TableChangedEventArgs e)    {        // Clients notification here.    }} 

Hope this helps.


I have a solution1. Just create a Class with a static attribute bool.

public class OutilContext{    public static bool first = true;}
  1. In your Global.asax.cs, You should control the Session_Start void

    if (OutilContext.first == true){        OutilContext.first = false;        NotificationComponent NC = new NotificationComponent();        var currentTime = DateTime.Now;        NC.RegisterNotification(currentTime); }

That control a number of SqlDependency, because when a client accesses the application the Global Class create SqlDependency for each client.