Should I use LINQ's Skip()
and Take()
method for paging, or implement my own paging with a SQL query?
Which is most efficient? Why would I choose one over the other?
I'm using SQL Server 2008, ASP.NET MVC and LINQ.
Should I use LINQ's Skip()
and Take()
method for paging, or implement my own paging with a SQL query?
Which is most efficient? Why would I choose one over the other?
I'm using SQL Server 2008, ASP.NET MVC and LINQ.
Trying to give you a brief answer to your doubt, if you execute the
skip(n).take(m)
methods on linq (with SQL 2005 / 2008 as database server) your query will be using theSelect ROW_NUMBER() Over ...
statement, with is somehow direct paging in the SQL engine.Giving you an example, I have a db table called
mtcity
and I wrote the following query (work as well with linq to entities):The resulting query will be:
Which is a windowed data access (pretty cool, btw cuz will be returning data since the very begining and will access the table as long as the conditions are met). This will be very similar to:
With the exception that, this second query will be executed faster than the linq result because it will be using exclusively the index to create the data access window; this means, if you need some filtering, the filtering should be (or must be) in the Entity listing (where the row is created) and some indexes should be created as well to keep up the good performance.
Now, whats better?
If you have pretty much solid workflow in your logic, implementing the proper SQL way will be complicated. In that case LINQ will be the solution.
If you can lower that part of the logic directly to SQL (in a stored procedure), it will be even better because you can implement the second query I showed you (using indexes) and allow SQL to generate and store the Execution Plan of the query (improving performance).
In 2008 we cant use Skip().Take()
The way is:
You can implement paging in this simple way by passing PageIndex
We use a CTE wrapped in Dynamic SQL (because our application requires dynamic sorting of data server side) within a stored procedure. I can provide a basic example if you'd like.
I haven't had a chance to look at the T/SQL that LINQ produces. Can someone post a sample?
We don't use LINQ or straight access to the tables as we require the extra layer of security (granted the dynamic SQL breaks this somewhat).
Something like this should do the trick. You can add in parameterized values for parameters, etc.
While LINQ-to-SQL will generate an
OFFSET
clause (possibly emulated usingROW_NUMBER() OVER()
as others have mentioned), there is an entirely different, much faster way to perform paging in SQL. This is often called the "seek method" as described in this blog post here.The
@previousScore
and@previousPlayerId
values are the respective values of the last record from the previous page. This allows you to fetch the "next" page. If theORDER BY
direction isASC
, simply use>
instead.With the above method, you cannot immediately jump to page 4 without having first fetched the previous 40 records. But often, you do not want to jump that far anyway. Instead, you get a much faster query that might be able to fetch data in constant time, depending on your indexing. Plus, your pages remain "stable", no matter if the underlying data changes (e.g. on page 1, while you're on page 4).
This is the best way to implement paging when lazy loading more data in web applications, for instance.
Note, the "seek method" is also called keyset paging.
LinqToSql will automatically convert a .Skip(N1).Take(N2) into the TSQL syntax for you. In fact, every "query" you do in Linq, is actually just creating a SQL query for you in the background. To test this, just run SQL Profiler while your application is running.
The skip/take methodology has worked very well for me, and others from what I read.
Out of curiosity, what type of self-paging query do you have, that you believe is more efficient than Linq's skip/take?