2016-06-15 15 views
5

Cerco di sviluppare un'applicazione asp.net mvc e anche di provare a usare signalr. Il problema è che ho due tabelle che controllano le notificazioni degli utenti nel progetto. Ho una tabella di notifica e anche una tabella di NotificationUser che è molte tabelle di notifica e tabelle utente. Sto provando che se un utente crea una notifica ad un altro utente nel sistema, provo a mostrare un pop-up che conferma l'utente con un semplice messaggio come "Hey! Nuova notifica ricevuta". Il problema è funzione javascript cambiamento di signalr colpendo tante passo times.All i utilizzata in signalR seguito elencatiPerché SignalR cambia la funzione colpendo molte volte?

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 [email protected] AND NtU_IsRead=0 
    END 

L'hub

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


} 

l'avvio Classe

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

    } 
} 

La vista parziale

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

At Last, The 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 che colpiscono tante volte se un utente di creare un notification.Where è il problema? Qualche idea? Non riesco a ottimizzarlo

MODIFICA 1 Sto chiamando NtfHub.NotifyChanges nel controller.

void dependancy_OnChange(object sender, SqlNotificationEventArgs e) 
    { 
     if (e.Type == SqlNotificationType.Change) 
     { 
      NtfHub.NotifyChanges(); 
     } 
    } 
+0

Dove stai chiamando 'NtfHub.NotifyChanges()'? È probabilmente in quel codice che il metodo server viene chiamato più volte, sia da JavaScript che da C# chiamandolo direttamente. Puoi [modificare] per aggiungere quel codice? – Rhumborl

+0

@Rhumborl ho editato il codice – mayk

+0

@Rumborando il suo errore come while (vero) ora – mayk

risposta

0

Anche se penso che SqlDependency è l'approccio sbagliato per questa funzione, si potrebbe tentare di risolvere questo problema specifico in questo modo:
Aggiungi parametro "subscribeToNotifications" per la vostra azione di controllo

public ActionResult GetNtf(bool subscribeToNotifications) 

Crea SqlDependency solo se è vero.
Poi iscriversi alla notifica solo sul mozzo iniziate (questo impedirà la creazione di molteplici SqlDependencies per lo stesso utente):

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

    }); 
} 

Ma essere consapevoli del fatto che ogni pagina di aggiornamento sarà comunque creare nuovo listener senza gestione delle sottoscrizioni sul lato server .

Opzione 2 è quello di creare un'unica SqlDependency (in fase di start application server) omettendo parametro userId - in ogni caso si sta inviando la notifica a tutti gli gli utenti non importa che uno ha ottenuto il messaggio.

Opzione 3 - la vera soluzione è sbarazzarsi di SqlDependency a tutti e inviare la notifica solo a specifici utente (destinatario del messaggio)

0

La ragione è che non si è annullare la sottoscrizione dall'evento dependancy_OnChange , un trigger di sqldependency è un'esecuzione one shot, quindi devi iscriverti a quello nuovo ogni volta che si attiva, ciò che non stai facendo è annullare l'iscrizione dal precedente gestore di eventi, quindi quando ti iscrivi a quello nuovo, ora hai più gestori per lo stesso 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

grazie per la risposta, ma non ha colpito la funzione di script notification.client.notifyChanges = function() { getData(); toastr.warning ("Ehi, hai Ntf"); }; now – mayk

+0

Prova a prendere il contesto fuori non dovresti averlo bisogno, l'hub dovrebbe già averlo. Clients.All.notifyChanges(); –

Problemi correlati