Проблема с обновлением SignalR и SqlDependency — ASP.NET

У меня есть таблица в базе данных MSSQL, и у меня есть страница ASPX, мне нужно отправить все новые строки на страницу в порядке убывания. Я нашел это замечательное руководство, в котором используется SignalR. и SqlDependency, и он показывает только последнюю строку, исключая предыдущие строки, которые были добавлены, когда я в сети, он делает это, потому что у него есть элемент span для отображения данных, и каждый раз, когда он перезаписывает этот диапазон, поэтому я изменил код JavaScript на добавьте новые данные, и он отлично работает.

Теперь проблема в том, что когда я обновил страницу в первый раз, я получу новые строки дважды, а если я обновлю страницу еще раз, я получу новые строки втрое... и так далее.

Единственное решение - закрыть приложение и снова открыть его, это похоже на сброс IIS.

Итак, что я могу сделать, чтобы избежать дублирования данных в онлайн-шоу?


person Ahmed Negm    schedule 21.05.2015    source источник
comment
@ Ручира, пожалуйста, помогите.   -  person Ahmed Negm    schedule 21.05.2015
comment
Не могли бы вы предоставить javascript и код на стороне сервера? Проблема где-то там.   -  person dyatchenko    schedule 21.05.2015
comment
Тот же код здесь: ruchirac.blogspot.com/2014 /10/   -  person Ahmed Negm    schedule 21.05.2015
comment
Но вы сказали, что изменили JavaScript   -  person dyatchenko    schedule 21.05.2015
comment
Исходный код js был $(#newData).html(msg); и я изменил его на $(#newData).html(msg + '‹br /›' + $(#newData).html());. Я изменил только способ просмотра.   -  person Ahmed Negm    schedule 21.05.2015
comment
Исходный код js был $(#newData).html(msg); и я изменил его на $(#newData).html(msg + '‹br /›' + $(#newData).html());. Я изменил только способ просмотра.   -  person Ahmed Negm    schedule 21.05.2015


Ответы (2)


Это не проблема SignalR, это происходит из-за того, что в упомянутом руководстве есть ряд ошибок, наиболее очевидной из которых является тот факт, что он постоянно создает экземпляры SqlDependency, но затем уничтожает их, не отписываясь от события OnChange. Вы должны начать с добавления чего-то вроде этого:

SqlDependency dependency = sender as SqlDependency;
dependency.OnChange -= dependency_OnChange;

перед вызовом SendNotifications внутри вашего обработчика событий. Проверьте это для вдохновения.

ОБНОВЛЕНИЕ (предыдущий ответ не совсем точен, но сохранен для контекста)

Основная проблема здесь заключается в том, что этот метод создает своего рода автоматически восстанавливающуюся бесконечную последовательность SqlDependencies из внутренних экземпляров страниц Web Forms, что делает их недоступными, как только ваша страница завершит рендеринг. Это означает, что после завершения жизненного цикла вашей страницы и ее отображения цепочка зависимостей остается живой и продолжает работать, даже если созданный экземпляр страницы завершил свой цикл. Обработчик событий также сохраняет активным экземпляр страницы, даже если он недоступен, что приводит к утечке памяти.

Единственный способ, которым вы можете это контролировать, — это генерировать эти цепочки где-то еще, например, внутри статического типа, который вы можете вызывать, передавая какой-то уникальный идентификатор (может быть, комбинацию имени страницы и имени пользователя? Это зависит от вашей логики). При первом вызове он будет делать то, что сейчас происходит в вашем текущем коде, но как только вы сделаете другой вызов с теми же параметрами, он ничего не сделает, поэтому ранее созданная цепочка останется единственной, уведомляющей, без повторяющихся вызовов. .

Это всего лишь предложение, возможных решений может быть много, но вам нужно понимать исходную проблему и тот факт, что практически невозможно удалить эти цепочки автоматически восстанавливающихся зависимостей, если вы не найдете способ их отслеживать. и создавать их только при необходимости. Я надеюсь, что эта часть ясна.

PS: это поведение очень похоже на то, что вы иногда получаете с утечкой обработчиков событий и сохранением живых объектов, которые должны быть убиты, это то, что обмануло меня в предыдущем ответе. Это в некотором роде похожая проблема (утечка объектов), но с совершенно другой причиной. Руководство, которому вы следуете, не разъясняет этого и приводит вас к ситуации, когда фантомный код продолжает выполняться, а память теряется.

person Wasp    schedule 21.05.2015
comment
SqlDependency не запускает событие дважды. Чтобы обеспечить непрерывный поток событий, вы должны снова и снова создавать SqlDependency. - person dyatchenko; 21.05.2015
comment
@dyatchenko а как ты думаешь? - person Ahmed Negm; 21.05.2015
comment
@AhmedNegm Вы также пытались остановить старую зависимость? - person Wasp; 21.05.2015
comment
@Wasp, да, я остановил его при загрузке страницы и снова открыл, а также остановил его в событии Application_End - person Ahmed Negm; 21.05.2015
comment
@dyatchenko вы правы, у меня смешанные воспоминания, давно ими не пользовался + куча доков, даже официальные, рекомендуя удалить обработчики. - person Wasp; 21.05.2015

Я получил это, хотя мне это абсолютно не нравится, я объявил статический член в файле Global.asax и в событии Page_Load я проверил его значение, если оно было истинным, не запускайте новый экземпляр SqlDependency, в противном случае запустить его.

if (!Global.PageIsFired)
            {
                Global.PageIsFired = true;
                SqlDependency.Stop(ConfigurationManager.ConnectionStrings["db"].ConnectionString);
                SqlDependency.Start(ConfigurationManager.ConnectionStrings["db"].ConnectionString);
                SendNotifications();
            }

Уважаемый @Wasp, Ваше последнее обновление очень помогло мне понять проблему, поэтому большое спасибо за ваше время и оперативную поддержку.

Уважаемый @dyatchenko, Большое спасибо за ваши комментарии, они тоже были очень полезными.

person Ahmed Negm    schedule 24.05.2015