我有一个C#MVC4网络应用程序,我正在试图找出linq语句。 (如果可能的话,Lambda)
我有两张桌子,Hits和Posts。点击跟踪对网站上每个页面的所有访问。帖子就像博客条目。当用户访问帖子时,PostId将记录在Hit表中。
表:
点击 HitId,Url,PostId
帖子 PostId,PostDate等
该网站的一个类别是“观看次数最多”,它将显示按点击次数下降的观看次数最多的帖子。
最后,我使用的是IPagedList,因此请记住最终列表需要进行Ordered。
我尝试了什么:
var postCount =
_db.Posts.Join(_db.Hits, posts => posts.PostId, hits => hits.PostId, (posts, hits) => new { posts, hits })
.GroupBy(num => num.posts.PostId)
.OrderByDescending(gp => gp.Count())
.Select(g => g.Key).ToList();
var results = _db.Posts.Where(p => postCount.Contains(p.PostId));
const int pageSize = 5;
var pageNumber = (page ?? 1);
return View(results.ToPagedList(pageNumber, pageSize));
所以postCount是MostViewed订购的PostId列表,这就是我想要的。但是因为我正在使用IPagedList,所以我收到了这个错误:
The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
任何帮助表示赞赏!谢谢!
感谢任何想要帮助的人。
如果我添加.ToList():
var results = _db.Posts.Where(p => all2.Contains(p.PostId)).ToList();
这解决了错误,但它仍然失去了postCount的顺序。它现在只是按PostId排序。
也许有更好的方法可以做到这一点?
答案 0 :(得分:2)
该代码看起来非常复杂。您可以通过按帖子的点击次数对帖子进行排序,将其减少为一个查询,如下所示:
var results = from post in _db.Posts
join hit in _db.Hits
on post.PostId equals hit.PostId
group hit by post into g
orderby g.Count() descending
select g.Key;
return View(results.ToPagedList(page ?? 1, 5));
这将转化为类似的东西:
SELECT Post.PostId, Post.PostDate, Post.Whatever, ..., COUNT(*) C
FROM Post
INNER JOIN Hit ON Post.PostId = Hit.PostId
GROUP BY Post.PostId, Post.PostDate, Post.Whatever, ...
ORDER BY C DESC
OFFSET @offset ROWS
FETCH NEXT @pageSize ROWS ONLY
此外,通过向查询添加.ToList()
,它将从数据库中获取所有内容并在内存中进行过滤,这可能会慢很多,具体取决于服务器和数据库之间的连接。
答案 1 :(得分:1)
以下内容如何:
var results = _db.Posts.Join(_db.Hits, posts => posts.PostId, hits => hits.PostId, (posts, hits) => new { posts, hits })
.GroupBy(num => num.posts)
.OrderByDescending(gp => gp.Count())
.Select(g => g.Key)
.ToList();