Just curious as to how Skip & Take are supposed to work. I\'m getting the results I want to see on the client side, but when I hook up the AnjLab SQL Profiler and look a
If you are using SQL Server as DB
Then you can convert
context.Users.OrderBy(u => u.Id)
.Skip(() => 10)
.Take(() => 5)
.ToList
=>
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent1]
ORDER BY [Extent1].[Id] ASC
OFFSET 10 ROWS FETCH NEXT 5 ROWS ONLY
refrence: https://anthonychu.ca/post/entity-framework-parameterize-skip-take-queries-sql/
I created simple extension:
public static IEnumerable<T> SelectPage<T, T2>(this IEnumerable<T> list, Func<T, T2> sortFunc, bool isDescending, int index, int length)
{
List<T> result = null;
if (isDescending)
result = list.OrderByDescending(sortFunc).Skip(index).Take(length).ToList();
else
result = list.OrderBy(sortFunc).Skip(index).Take(length).ToList();
return result;
}
Simple use:
using (var context = new TransportContext())
{
var drivers = (from x in context.Drivers where x.TransportId == trasnportId select x).SelectPage(x => x.Id, false, index, length).ToList();
}
The following works and accomplishes the simplicity I was looking for:
public IEnumerable<Store> ListStores(Expression<Func<Store, string>> sort, bool desc, int page, int pageSize, out int totalRecords)
{
List<Store> stores = new List<Store>();
using (var context = new TectonicEntities())
{
totalRecords = context.Stores.Count();
int skipRows = (page - 1) * pageSize;
if (desc)
stores = context.Stores.OrderByDescending(sort).Skip(skipRows).Take(pageSize).ToList();
else
stores = context.Stores.OrderBy(sort).Skip(skipRows).Take(pageSize).ToList();
}
return stores;
}
The main thing that fixed it for me was changing the Func sort parameter to:
Expression<Func<Store, string>> sort
Entity Framework 6 solution here...
http://anthonychu.ca/post/entity-framework-parameterize-skip-take-queries-sql/
e.g.
using System.Data.Entity;
....
int skip = 5;
int take = 10;
myQuery.Skip(() => skip).Take(() => take);
As long as you don't do it like queryable.ToList().Skip(5).Take(10)
, it won't return the whole recordset.
Take
Doing only Take(10).ToList()
, does a SELECT TOP 10 * FROM
.
Skip
Skip works a bit different because there is no 'LIMIT' function in TSQL. However it creates an SQL query that is based on the work described in this ScottGu blog post.
If you see the whole recordset returned, it probably is because you are doing a ToList()
somewhere too early.
Try this:
public IEnumerable<Store> ListStores(Func<Store, string> sort, bool desc, int page, int pageSize, out int totalRecords)
{
var context = new TectonicEntities();
var results = context.Stores;
totalRecords = results.Count();
int skipRows = (page - 1) * pageSize;
if (desc)
results = results.OrderByDescending(sort);
return results.Skip(skipRows).Take(pageSize).ToList();
}
in truth, that last .ToList() isn't really necessary as you are returning IEnumerable...
There will be 2 database calls, one for the count and one when the ToList() is executed.