Dapper - 具有单一返回值的多重映射
下面是我用来返回对象分页列表的代码:
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);
}
}
虽然这有效,但这意味着我必须定义我的条件两次,一次用于计数查询,一次用于结果集查询。我可以只执行一个查询,而不是诉诸字符串连接:
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";
但是,我似乎无法使用 Dapper 来映射它。我不能使用与上面相同的方法,因为没有多个结果。我尝试过使用多重映射,但这预计会返回 IEnumerable。
我将如何映射到以下内容?
public class PostList
{
public IEnumerable<PostModel> Posts;
public int TotalCount { get; set; }
}
谢谢
本
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧...你不会...
你必须修改你的 PostModel 以包含 TotalCount 属性...这真的很难看。或者执行动态并在
Select
中重新映射它,这也很难看。你看,你用
count(*) over() 返回 count(*) N 次...这是一个 hack,使用这个 hack 并不一定更快。我测量到在某些情况下它比运行双重查询要慢,特别是您可以快捷方式选择
select count(*)
中的某些索引,因为您没有选择所有列。此外,黑客还禁用了某些分页优化,例如您无法将select top N
添加到查询中。我对分页查询的建议是正确建立索引,这是关键。测量性能并查看此技巧是否确实有帮助(当正确的索引到位时)。
我关注有关字符串连接的问题,但您始终可以为此定义通用帮助器方法。
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 theselect count(*)
since you are not selecting all the columns. Additionally the hack disables certain paging optimisations, for example you can not addselect 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.