Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.SqlDependency_OnChange C# (CSharp) Method

SqlDependency_OnChange() private method

private SqlDependency_OnChange ( System.Data.SqlClient.SqlNotificationEventArgs e, DbOperation>.Action processRecord ) : void
e System.Data.SqlClient.SqlNotificationEventArgs
processRecord DbOperation>.Action
return void
        protected virtual void SqlDependency_OnChange(SqlNotificationEventArgs e, Action<IDataRecord, DbOperation> processRecord)
        {
            Trace.TraceInformation("{0}SQL notification change fired", TracePrefix);

            lock (_stopLocker)
            {
                if (_disposing)
                {
                    return;
                }
            }

            var previousState = Interlocked.CompareExchange(ref _notificationState,
                NotificationState.NotificationReceived, NotificationState.ProcessingUpdates);

            if (previousState == NotificationState.NotificationReceived)
            {
                Trace.TraceError("{0}Overlapping SQL change notifications received, this should never happen, BUG!", TracePrefix);
                
                return;
            }
            if (previousState == NotificationState.ProcessingUpdates)
            {
                // We're still in the original receive loop

                // New updates will be retreived by the original reader thread
                Trace.TraceVerbose("{0}Original reader processing is still in progress and will pick up the changes", TracePrefix);

                return;
            }

            // _notificationState wasn't ProcessingUpdates (likely AwaitingNotification)

            // Check notification args for issues
            if (e.Type == SqlNotificationType.Change)
            {
                if (e.Info == SqlNotificationInfo.Update)
                {
                    Trace.TraceVerbose("{0}SQL notification details: Type={1}, Source={2}, Info={3}", TracePrefix, e.Type, e.Source, e.Info);
                }
                else if (e.Source == SqlNotificationSource.Timeout)
                {
                    Trace.TraceVerbose("{0}SQL notification timed out", TracePrefix);
                }
                else
                {
                    Trace.TraceError("{0}Unexpected SQL notification details: Type={1}, Source={2}, Info={3}", TracePrefix, e.Type, e.Source, e.Info);

                    Faulted(new SqlMessageBusException(String.Format(CultureInfo.InvariantCulture, Resources.Error_UnexpectedSqlNotificationType, e.Type, e.Source, e.Info)));
                }
            }
            else if (e.Type == SqlNotificationType.Subscribe)
            {
                Debug.Assert(e.Info != SqlNotificationInfo.Invalid, "Ensure the SQL query meets the requirements for query notifications at http://msdn.microsoft.com/en-US/library/ms181122.aspx");

                Trace.TraceError("{0}SQL notification subscription error: Type={1}, Source={2}, Info={3}", TracePrefix, e.Type, e.Source, e.Info);

                if (e.Info == SqlNotificationInfo.TemplateLimit)
                {
                    // We've hit a subscription limit, pause for a bit then start again
                    Thread.Sleep(2000);
                }
                else
                {
                    // Unknown subscription error, let's stop using query notifications
                    _notificationState = NotificationState.Disabled;
                    try
                    {
                        SqlDependency.Stop(ConnectionString);
                    }
                    catch (Exception) { }
                }
            }

            Changed();
        }