views:

425

answers:

3

After many hours, I finally realize that I am working correctly with the Cache object in my ASP.NET application but my stored procedures stops it from working correctly.

This stored procedure works correctly:

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

But this (the one I wanted) doesn't:

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

I gave the @TotalRecords parameter the value 10 so you can be sure that the problem is not from the COUNT(*) function which I know is not supported well.

Also, when I run it from SQL Server Management Studio, it does exactly what it should do. In the ASP.NET application the results are retrieved correctly, only the cache is somehow unable to work!

Can you please help?

Maybe a hint

I believe that the reason why the dependency HasChanged property is related to the fact that the column Row generated from the ROW_NUMBER is only temporary and, therefore, the SQL SERVER is not able to to say whether the results are changed or not. That's why HasChanged is always set to true.

Does anyone know how to paginate results from SQL SERVER without using COUNT or ROW_NUMBER functions?

+1  A: 

not enough cache size.

EffoStaff Effo
With only 2 very small cache elements, that's absolutely impossible, but thanks for trying.
Fabio Milheiro
why i think so is that it looks like cache conflicts, means the cache is always being updated during query, say too much data exchanging between the storage(i.e. harddisk) and the cache in your 2nd case. so i think enlarge cache works.
EffoStaff Effo
I still think it's quite difficult to solve this problem that way, but can you tell me then how to enlarge it?
Fabio Milheiro
A: 

Sql cache dependency for .NET 3.5 only works for simple queries. Maybe .NET 4 will surprise me.

Fabio Milheiro
Any references on it?
vgv8
A: 

1 - Can you copy & paste the code you actually use to cache the results of that sproc ? 2 - Have you tried a sproc where you use straight query instead of EXEC-ing a string ?

Yes #2 means that you can't change the structure of the query on the fly :-) but unless you are calculating your own caching criteria in #1 that's the rule of caching you have to abide by in general. No caching mechanism is ever going to parse a string from EXEC from you.

EXEC-ing a string in a sproc makes that sproc a total toss of a coin on each and every run even for SQL Server itself. It also leaves you open to script injection attacks since your query is still being composed by strings at run time - it's not any different from composing the whole string in C# and passing it to sproc to "just EXEC whatever is inside"

ZXX
@zb_z, I can't remember in which forms I tried the sproc. I'll be back to that part of the application soon, maybe using .NET 4 and see how I can do it. Then I'll post the code so you can check it out.
Fabio Milheiro
Since you are trying to nail down an issue would be better to go with framework version you already know and kind of trust. Chances are that with a straight sproc (no execs with strings) it might start working. BTW you don't need actual web server in order to use "web cache" classes with dependency filing. They are perfecly normal classes with thread-safe hash-tables and no IIS tie-ups.Oh and one thing to remember - dependency condition evaluation is always lazy - gets checked only when someone actually asks for the object. May or may not affect you in this particular case.
ZXX