Cache и 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()? Если да, есть ли другой способ разбить результаты на страницы?

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

3 ответа

Решение

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

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

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

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

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

Я был в состоянии соединить это от следующих до сообщений MSDN.

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

https://social.msdn.microsoft.com/Forums/en-US/cf3853f3-0ea1-41b9-987e-9922e5766066/changing-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

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

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

Просто предположение, но может ли это быть потому, что ваш 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

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

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

".... Оператор не должен содержать подзапросов, внешних объединений или самостоятельных объединений....."

Я также нашел некоторую бесценную информацию по устранению неполадок от парня из Redgate здесь: Использование и мониторинг уведомлений о запросах SQL 2005, которые помогли мне решить мою собственную проблему: с помощью Sql Profiler для отслеживания событий QN, которые он предлагает, я смог определить, что мое соединение было неправильно используя опцию "SET ARITHABORT OFF", чтобы мои уведомления перестали работать.

Другие вопросы по тегам