Почему хранимая процедура делает недействительной зависимость от кэша SQL?
-
20-09-2019 - |
Вопрос
Спустя много часов я наконец осознаю, что правильно работаю с объектом Cache в своем приложении ASP.NET, но мои хранимые процедуры мешают ему работать правильно.
Эта хранимая процедура работает правильно:
CREATE PROCEDURE [dbo].[ListLanguages]
@Page INT = 1,
@ItemsPerPage INT = 10,
@OrderBy NVARCHAR (100) = 'ID',
@OrderDirection NVARCHAR(4) = 'DESC'
AS
BEGIN
SELECT ID, [Name], Flag, IsDefault FROM dbo.Languages
END
Но это (тот, который я хотел) не:
CREATE PROCEDURE [dbo].[ListLanguages]
@Page INT = 1,
@ItemsPerPage INT = 10,
@OrderBy NVARCHAR (100) = 'ID',
@OrderDirection NVARCHAR(4) = 'DESC',
@TotalRecords INT OUTPUT
AS
BEGIN
SET @TotalRecords = 10
EXEC('SELECT ID, Name, Flag, IsDefault FROM (
SELECT ROW_NUMBER() OVER (ORDER BY ' + @OrderBy + ' ' + @OrderDirection + ') as Row, ID, Name, Flag, IsDefault
FROM dbo.Languages) results
WHERE Row BETWEEN ((' + @Page + '-1)*' + @ItemsPerPage + '+1) AND (' + @Page + '*' + @ItemsPerPage + ')')
END
Я присвоил параметру @TotalRecords значение 10, чтобы вы могли быть уверены, что проблема не в функции COUNT(*), которая, как я знаю, плохо поддерживается.
Кроме того, когда я запускаю его из SQL Server Management Studio, он делает именно то, что должен.В приложении ASP.NET результаты извлекаются корректно, вот только кэш почему-то не работает!
Можете ли вы помочь?
Может быть, подсказка
Я считаю, что причина, по которой свойство HasChanged зависимости, связана с тем фактом, что строка столбца, сгенерированная из ROW_NUMBER, является временной и, следовательно, SQL SERVER не может сказать, изменились ли результаты или нет.Вот почему HasChanged всегда имеет значение true.
Кто-нибудь знает, как разбивать результаты SQL SERVER на страницы без использования функций COUNT или ROW_NUMBER?
Решение 2
Зависимость кэша Sql для .NET 3.5 работает только для простых запросов.Возможно, .NET 4 меня удивит.
Другие советы
недостаточно размера кэша.
1. Можете ли вы скопировать и вставить код, который вы фактически используете для кэширования результатов этой процедуры?2. Пробовали ли вы процедуру, в которой вы используете прямой запрос вместо выполнения строки EXEC?
Да, № 2 означает, что вы не можете изменить структуру запроса на лету :-) но если вы не рассчитываете свои собственные критерии кэширования в № 1, это правило кэширования, которое вы должны соблюдать в целом.Ни один механизм кэширования никогда не сможет проанализировать строку из EXEC от вас.
Выполнение EXEC строки в процедуре превращает эту процедуру в сплошное подбрасывание монеты при каждом запуске даже для самого SQL Server.Это также оставляет вас открытым для атак путем внедрения скриптов, поскольку ваш запрос по-прежнему состоит из строк во время выполнения - это ничем не отличается от составления всей строки в C # и передачи ее в sproc для «просто EXEC того, что находится внутри».