Below is the code I'm using to return a paged list of objects:
string query2 = @"
select count(*) as TotalCount from blogposts p where p.Deleted = 0 and p.PublishDate <= @date
select * from (
select p.*,
row_number() over(order by publishdate desc) as rownum
from blogposts as p
where p.Deleted = 0 and p.PublishDate <= @date
) seq
where seq.rownum between @x and @y";
using (var cn = new SqlConnection(connectionString))
{
cn.Open();
using (var multi = cn.QueryMultiple(query2, new { x= lower, y = upper, date = DateTime.UtcNow }))
{
var totalCount = multi.Read<int>().Single();
var posts = multi.Read<PostModel>().ToList();
return new PagedList<PostModel>(posts, page, pageSize, x => totalCount);
}
}
Although this works, it means that I have to define my criteria twice, once for the count query and once for the resultset query. Rather than resort to string concatenation, I can execute just one query:
string query = @"
select * from (select p.*,
row_number() over(order by publishdate desc) as rownum,
count(*) over() as TotalCount
from blogposts as p) seq
where seq.rownum between @x and @y";
However, I don't seem able to map this using Dapper. I can't use the same method as above because there aren't multiple results. I've tried using multi mapping but this expects to return an IEnumerable.
How would I map to the following?
public class PostList
{
public IEnumerable<PostModel> Posts;
public int TotalCount { get; set; }
}
Thanks
Ben
Well ... you wouldn't ...
You would have to amend your PostModel to include a TotalCount property ... which is really ugly. Or execute a dynamic and remap it in a Select
which is also ugly.
You see, you are returning count(*) N times with count(*) over()
... it is a hack, using this hack is not necessarily faster. I have measured it being slower than running a double query in some of my scenarios, in particular you can shortcut some indexes in the select count(*)
since you are not selecting all the columns. Additionally the hack disables certain paging optimisations, for example you can not add select top N
to the query.
My recommendation around paging queries would be to get indexing right, it is key. Measure perf and see if this hack actually helps (when the correct indexing is in place).
I follow about the concerns around string concatenation, but you can always define general helper methods for that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With