2015-07-27 3 views
3

Я разрабатываю систему уведомлений с использованием SqlDependency и signalR, проблема, с которой я не могу справиться, заключается в изменении значения атрибута IsOnline в БД на True или False, основанный на статусе участника, событие OnChange срабатывает много раз, при первом входе в систему пользователя я получаю два уведомления, а во второй раз я получаю больше, чем 4, затем больше, чем больше. Количество уведомлений увеличивается каждый раз, когда новый вход или выход. Я уверен, что проблема в SqlDependency не в SignalR, я собираюсь поделиться с вами частью моего кода.SqlDependency OnChange Событие Многократно срабатывает для каждого события в базе данных

Заранее спасибо.

[System.Web.Services.WebMethod] 

    public static IEnumerable<AttendeeList> GetAllUsers() 
    { 
     var AttendeeList = new List<AttendeeList>(); 

     try 
     { 
      using (var connection = new SqlConnection(_connString)) 
      { 
       connection.Open(); 
       string str = ""; 
       str += "SELECT [AttendeeID], "; 
       str += "  [IsAllowToUploadDocuments],"; 
       str += "  [IsOnline], "; 
       str += "  [AttendeeTypeName],"; 
       str += "  [UserName] "; 
       str += "  FROM [dbo].[Meeting_Attendees] "; 
       str += "  INNER JOIN [dbo].[aspnet_Users] ON [aspnet_Users].[UserId] = [Meeting_Attendees].[AttendeeID] "; 
       str += "  INNER JOIN [dbo].[AttendeeType] ON [dbo].[AttendeeType].[AttendeeTypeID] = [dbo].[Meeting_Attendees].[AttendeeTypeID] "; 
       str += "  WHERE [MeetingID][email protected] ORDER BY [IsOnline] DESC"; 

       using (var command = new SqlCommand(@str, connection)) 
       { 
        SqlParameter prm = new SqlParameter("@MeetingID", SqlDbType.Int); 
        prm.Direction = ParameterDirection.Input; 
        prm.DbType = DbType.Int32; 
        prm.Value = Convert.ToInt32(Properties.Settings.Default.MeetingID); 
        command.Parameters.Add(prm); 
        command.Notification = null; 

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

        if (connection.State == ConnectionState.Closed) 
         connection.Open(); 

        var reader = command.ExecuteReader(); 

        while (reader.Read()) 
        { 
         AttendeeList.Add(item: new AttendeeList { UserName = (string)reader["UserName"], UserType = (string)reader["AttendeeTypeName"], IsOnline = (bool)reader["IsOnline"], IsAllowToUploadDocuments = (bool)reader["IsAllowToUploadDocuments"], IsCurrentUser = true ? (Guid)reader["AttendeeID"] == new Guid(Properties.Settings.Default.UserID.ToString()) : false }); 
        } 
       } 
      } 
     } 
     catch { } 
     return AttendeeList; 
    } 

    private static void dependencyUsers_OnChange(object sender, SqlNotificationEventArgs e) 
    { 
     if (e.Type == SqlNotificationType.Change && e.Info == SqlNotificationInfo.Update) 
     { 
      //Call SignalR 
      MessagesHub.UpdateUsers(); 
     } 
    } 

ответ

0

Запрос уведомление огня, когда контролируемый набор результатов может изменилось, см Understanding When Query Notifications Occur. Как правило, вы можете получать больше уведомлений, чем фактические изменения данных:

Обратите внимание, что SQL Server может выдавать уведомление о запросе в ответ на события, которые не меняют данные, или в ответ на изменение, которое не фактически влияют на результаты запроса. Например, когда оператор UPDATE изменяет одну из строк, возвращаемых запросом, уведомление может срабатывать, даже если обновление строки не изменило столбцы в результатах запроса. Уведомления о запросах предназначены для поддержки общей цели улучшения производительность для приложений, которые кэшируют данные. Когда сервер сильно загружен, SQL Server может выдать уведомление о запросе для подписки, а не выполнять работу по определению того, изменились ли результаты запроса.

Неполадка, которая вызывает проблемы в вашем случае, невозможно сообщить из вашего сообщения, в частности, неясно, как вы обрабатываете обновления, чтобы в результате появилось еще четыре уведомления. Получение 4 уведомлений означает, что вы отправили 4 запроса для уведомления, поэтому, вероятно, у вас есть проблема и в вашем коде, и вы переписываете.

Прочтите Using SQL Trace to Troubleshoot Query Notifications и попытайтесь устранить неполадки в том, что происходит, когда созданные и недействительные уведомления.

0

Я падаю в том же номере при использовании SignalR и SQL Завис

Линия получения выполняется более чем один раз. Мероприятие должно быть подписано только один раз. oDependency.OnChange + = новый OnChangeEventHandler (DBUpdateNotificationReived);

0

У меня также была такая же проблема с несколькими вызовами по событию OnChange в моем проекте, но я исправил его с помощью счетчик. Следуя этому примеру, в моем случае функция dependencyUsers_OnChange из примера включала дважды.

Я инициализировал переменную счетчика как глобальную. После «сканирования» состояния ваших временных данных перед любым изменением я также устанавливаю значение счетчик на 0.

После вашего примера, после этого шага, модификация была сделана на dependencyUsers_OnChange в if заявлении:

private static void dependencyUsers_OnChange(object sender, SqlNotificationEventArgs e) 
    { 
      if (e.Type == SqlNotificationType.Change && e.Info == SqlNotificationInfo.Update && counter == 0) 
      { 
       //Call SignalR 
       MessagesHub.UpdateUsers(); 
       counter++; //The update is done once 
      } 
      else 
      { 
       counter = 0; //if the update is needed in the same iteration, please don't update and set the counter to 0 
      } 
    } 

В вашем случае, решение будет что-то вроде:

int counter = 0; //initialization of help counter 
[System.Web.Services.WebMethod] 

    public static IEnumerable<AttendeeList> GetAllUsers() 
    { 
     var AttendeeList = new List<AttendeeList>(); 

     try 
     { 
      using (var connection = new SqlConnection(_connString)) 
      { 
       connection.Open(); 
       string str = ""; 
       str += "SELECT [AttendeeID], "; 
       str += "  [IsAllowToUploadDocuments],"; 
       str += "  [IsOnline], "; 
       str += "  [AttendeeTypeName],"; 
       str += "  [UserName] "; 
       str += "  FROM [dbo].[Meeting_Attendees] "; 
       str += "  INNER JOIN [dbo].[aspnet_Users] ON [aspnet_Users].[UserId] = [Meeting_Attendees].[AttendeeID] "; 
       str += "  INNER JOIN [dbo].[AttendeeType] ON [dbo].[AttendeeType].[AttendeeTypeID] = [dbo].[Meeting_Attendees].[AttendeeTypeID] "; 
       str += "  WHERE [MeetingID][email protected] ORDER BY [IsOnline] DESC"; 

       using (var command = new SqlCommand(@str, connection)) 
       { 
        SqlParameter prm = new SqlParameter("@MeetingID", SqlDbType.Int); 
        prm.Direction = ParameterDirection.Input; 
        prm.DbType = DbType.Int32; 
        prm.Value = Convert.ToInt32(Properties.Settings.Default.MeetingID); 
        command.Parameters.Add(prm); 
        command.Notification = null; 

        var dependency = new SqlDependency(command); 
        counter = 0; //Whenewer the web method is called, set te counter to 0 
        dependency.OnChange += new OnChangeEventHandler(dependencyUsers_OnChange); 

        if (connection.State == ConnectionState.Closed) 
         connection.Open(); 

        var reader = command.ExecuteReader(); 

        while (reader.Read()) 
        { 
         AttendeeList.Add(item: new AttendeeList { UserName = (string)reader["UserName"], UserType = (string)reader["AttendeeTypeName"], IsOnline = (bool)reader["IsOnline"], IsAllowToUploadDocuments = (bool)reader["IsAllowToUploadDocuments"], IsCurrentUser = true ? (Guid)reader["AttendeeID"] == new Guid(Properties.Settings.Default.UserID.ToString()) : false }); 
        } 
       } 
      } 
     } 
     catch { } 
     return AttendeeList; 
    } 

    private static void dependencyUsers_OnChange(object sender, SqlNotificationEventArgs e) 
    { 
      if (e.Type == SqlNotificationType.Change && e.Info == SqlNotificationInfo.Update && counter == 0) 
      { 
       //Call SignalR 
       MessagesHub.UpdateUsers(); 
       counter++; //The update is done once 
      } 
      else 
      { 
       counter = 0; //if the update is needed in the same iteration, please don't update and set the counter to 0 
      } 
    } 

Я надеюсь, что это идея будет полезна для кого-то, я решил проблему в своем проекте с помощью этого решения.

 Смежные вопросы

  • Нет связанных вопросов^_^