开发者

Dapper - Multi Mapping with a single return value

开发者 https://www.devze.com 2023-03-09 19:54 出处:网络
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

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<Pos开发者_开发百科tModel>(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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号