ASP.Net MVC Linq分组查询

时间:2009-10-12 21:50:17

标签: asp.net-mvc linq

我使用以下

获取数据库中的最后20条更新记录
var files = (from f in filesContext.Files
                         join ur in filesContext.aspnet_Roles on f.Authority equals ur.RoleId
                         join u in filesContext.aspnet_Users on f.Uploader equals u.UserId
                         orderby f.UploadDate descending
                         select new FileInfo { File = f, User = u, UserRole = ur }).Take(20);

然后我在我看来将结果分开:

<%foreach(var group in Model.GroupBy(f => f.UserRole.RoleName)) {%>
//output table here

这很好,因为我的每个角色都会呈现一个表格。然而正如预期的那样,我总得到了最后20条记录,我怎样才能获得每个角色的最后20条记录?

所以我最终得到了:

UserRole1

//与此UserRole1相关的最近20条记录

UserRole2

//与此UserRole2相关的最近20条记录

UserRole3

//与此UserRole3相关的最近20条记录

2 个答案:

答案 0 :(得分:1)

我可以想到三种可行的方法。首先,获取所有角色,然后对每个角色执行Take(20)查询,将结果聚合到模型中。这可能是也可能不是很多不同的查询,具体取决于您拥有的角色数量。其次,获取所有结果,然后在视图中过滤每个角色的最后20个。这可能是一个非常大的查询,需要很多时间。第三,获得一些可能每个角色至少有20个条目的大量结果(但不保证),然后在视图中过滤每个角色的最后20个。我可能会使用第一个或第三个选项,具体取决于获得20个结果的重要性。

var files = (from f in filesContext.Files
             join ur in filesContext.aspnet_Roles on f.Authority equals ur.RoleId
             join u in filesContext.aspnet_Users on f.Uploader equals u.UserId
             orderby f.UploadDate descending
             select new FileInfo { File = f, User = u, UserRole = ur })
           .Take(2000);


<% foreach (var group in Model.GroupBy( f => f.UserRole.RoleName,
                                     (role,infos) =>
                                         new {
                                               Key = role.RoleName,
                                               Selected = infos.Take(20)
                                             } ))                                           { %>

   <%= group.Key %>
   <% foreach (var selection in group.Selected)
      { %>
        ...

答案 1 :(得分:0)

您可以计算元素并跳过第一个(长度为20个)元素,也可以反向/取20个/反向。

foreach (var group in Model.GroupBy(f => f.UserRole.RoleName))
{
    // draw table header
    foreach (item in group.Reverse().Take(20).Reverse())
    {
        // draw item
    }

    // Or
    int skippedElementCount = group.Count() - 20;
    if (skippedElementCount < 0) skippedElementCount = 0;

    foreach (item in group.Skip(skippedElementCount))
    {
        // draw item
    }

    // draw table footer
}