Кэш и SqlCacheDependency (ASP.NET MVC)

Нам нужно вернуть подмножество записей, и для этого мы используем следующую команду:

using (SqlCommand command = new SqlCommand(
                    "SELECT ID, Name, Flag, IsDefault FROM (SELECT ROW_NUMBER() OVER (ORDER BY @OrderBy DESC) as Row, ID, Name, Flag, IsDefault FROM dbo.Languages) results WHERE Row BETWEEN ((@Page - 1) * @ItemsPerPage + 1) AND (@Page * @ItemsPerPage)",
                    connection))

Я установил объявление SqlCacheDependency следующим образом:

SqlCacheDependency cacheDependency = new SqlCacheDependency(command);

Но сразу после запуска команды command.ExecuteReader() базовое свойство hasChanged объекта SqlCacheDependency становится истинным, хотя я никак не изменил результат запроса! И из-за этого результат этого запроса не сохраняется в кеше.

HttpRuntime.Cache.Insert( cacheKey, list, cacheDependency, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(AppConfiguration.CacheExpiration.VeryLowActivity));

Это потому, что команда имеет 2 оператора SELECT? Это ROW_NUMBER()? Если да, есть ли другой способ разбить результаты на страницы?

Пожалуйста помоги! После слишком многих часов немного будет высоко оценено! Спасибо


person Fabio Milheiro    schedule 08.10.2009    source источник


Ответы (3)


Столкнувшись с той же проблемой и найдя те же ответы в Интернете без какой-либо помощи, я пересматривал ответ о недопустимой подписке xml от профилировщика.

Я нашел пример на сайте поддержки msdn с немного другим порядком кода. Когда я попробовал это, я понял проблему: не открывайте объект подключения до тех пор, пока вы не создадите объект команды и объект зависимости кеша. Вот порядок, которому вы должны следовать, и все будет хорошо:

  1. Обязательно включите уведомления (SqlCahceDependencyAdmin) и сначала запустите SqlDependency.Start.
  2. Создайте объект соединения
  3. Создайте объект команды и назначьте текст команды, тип и объект соединения (любая комбинация конструкторов, установка свойств или использование CreateCommand).
  4. Создайте объект зависимости кеша sql
  5. Откройте объект соединения
  6. Выполнить запрос
  7. Добавить элемент в кеш, используя зависимость.

Если вы следуете этому порядку и выполняете все остальные требования к оператору выбора, у вас не будет проблем с разрешениями, это сработает!

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

Я смог собрать его воедино из следующих сообщений в msdn.

Этот пост был одной из наиболее распространенных причин недействительной подписки и показывает, как клиент .Net устанавливает свойства, которые отличаются от того, что требуется для уведомления.

https://social.msdn.microsoft.com/Forums/en-US/cf3853f3-0ea1-41b9-987e-9922e5766066/change-default-set-options-forced-by-net?forum=adodotnetdataproviders

Тогда этот пост был от пользователя, который, как и я, сократил свой код до простейшего формата. Мой исходный шаблон кода был похож на его.

https://social.technet.microsoft.com/Forums/windows/en-US/5a29d49b-8c2c-4fe8-b8de-d632a3f60f68/subscriptions-always-invalid-usual-suspects-checked-no-joy?forum=sqlservicebroker

Затем я нашел этот пост, также очень простое решение проблемы, только у него была простая проблема - для таблиц требовалось 2 имени части. В его случае предложение решило проблему. Посмотрев на его код, я заметил, что основное отличие заключается в ожидании открытия объекта соединения до тех пор, пока ПОСЛЕ создания объекта команды И объекта зависимости. Мое единственное предположение находится под капотом (я еще не начал рефлектор проверять, поэтому только предположение) объект Connection открывается по-другому, или порядок событий и команда происходят по-другому, из-за этой ассоциации.

https://social.msdn.microsoft.com/Forums/sqlserver/en-US/bc9ca094-a989-4403-82c6-7f608ed462ce/sql-server-not-creating-subscription-for-simple-select-query-when-using-sqlcachedependency?forum=sqlservicebroker

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

person rshadman    schedule 11.12.2014
comment
Я пришел к выводу, что, хотя это может принести пользу, это всего лишь средство для достижения цели, и компании никогда специально не просят об этом (очевидно). Существуют более простые методы достижения масштабируемости. Это звучит слишком деликатно, поскольку это странное поведение, которое не определено конкретно или, по крайней мере, четко не определено, может меняться между версиями, но рад узнать, что кто-то нашел решение. - person Fabio Milheiro; 12.12.2014

Просто предположение, но может ли это быть из-за того, что в вашем выражении SELECT нет пункта ORDER BY?

Если вы не укажете явный порядок, запрос может возвращать результаты в любом порядке при каждом запуске. Возможно, это заставляет объект SqlCacheDependency думать, что результаты изменились.

Попробуйте добавить предложение ORDER BY:

SELECT ID, Name, Flag, IsDefault
FROM
(
    SELECT ROW_NUMBER() OVER (ORDER BY @OrderBy DESC) AS Row,
        ID, Name, Flag, IsDefault
    FROM dbo.Languages
) AS results
WHERE Row BETWEEN ((@Page - 1) * @ItemsPerPage + 1) AND (@Page * @ItemsPerPage)
ORDER BY Row
person LukeH    schedule 08.10.2009
comment
Спасибо, но это не работает, потому что результаты уже заказаны... Я все еще пытался, и, к сожалению, мои ожидания оправдались. 1 балл за попытку :) - person Fabio Milheiro; 09.10.2009

я не эксперт по SqlCacheDependency, на самом деле, я нашел этот вопрос, когда искал ответы на свои собственные проблемы с ним! Однако я считаю, что причина, по которой ваш SqlCacheDependency не работает, заключается в том, что ваш SQL содержит вложенный подзапрос.

Взгляните на документацию, в которой указано, что вы можете/не можете использовать в своем SQL: Создание запроса для уведомления

"....Инструкция не должна содержать подзапросов, внешних или самостоятельных соединений...."

Я также нашел бесценную информацию об устранении неполадок от парня из Redgate здесь: Использование и мониторинг уведомлений о запросах SQL 2005, которые помогли мне решить мою собственную проблему: используя Sql Profiler для отслеживания событий QN, которые он предложил, я смог определить, что мое соединение было неправильное использование параметра «УСТАНОВИТЬ ARITHABORT OFF», что приводит к сбою моих уведомлений.

person shockstump    schedule 22.03.2010
comment
Да, это абсолютно верно, я уже пришел к такому выводу. В наши дни SqlCacheDependency по-прежнему бесполезен для большинства запросов, потому что, как мы видим в поддерживаемых операторах SELECT в вашей первой ссылке, ограничений слишком много! Для этого есть обходной путь, но он требует немного больше работы. Не устанавливайте зависимость кэша, и когда результат выбора редактируется или удаляется, вы используете ключ кэша для удаления кэшированного объекта. Если ваше приложение хорошо сделано, оно обязательно сработает. - person Fabio Milheiro; 23.03.2010