使用LINQ to SQL进行分页搜索结果

22

使用LINQ to SQL获取分页结果的最佳模式是什么?

我的场景如下:

假设我想通过description搜索items表。我可以轻松地执行以下操作:

public IQueryable<Item> FindItemsByDescription(string description)
{
   return from item in _dc.Items
          where item.Description.Contains(description);
}

现在,对于这个结果集,最好的分页方法是什么?

  1. 我应该在执行此操作之前执行一个 count 查询以找到结果集大小,然后根据需要限制此查询吗?我感觉这是正确的方式。
  2. 我应该执行完整的查询,从数组大小中获取计数,然后仅返回这个数组的分页子集吗?如果结果集足够大,我感觉这将是一种巨大的浪费时间...或者是LINQ to SQL在这里做了一些魔法?

LINQ to SQL是否有用于执行此操作的通用模式?

编辑:我必须澄清一件小事情。我知道 Take 和 Skip 方法。但是,在使用TakeSkip之前,我应该如何获得查询将检索的总计数

2个回答

33

分页的模式非常简单。它涉及使用Skip()和Take()扩展方法,如下所示:

public IQueryable<Item> FindItemsByDescription(string description, int pageIndex, int pageSize)
{
   return from item in _dc.Items
          where item.Description.
          Contains(description).
          Skip((pageIndex - 1) * pageSize).
          Take(pageSize);
}

更新:要获取总计数,只需使用Count()方法:

int totalCount = from item in _dc.Items
                 where item.Description.
                 Contains(description).Count();

int numberOfPages = (int)(totalCount/pageSize);
根据你要如何显示记录,你可以使用numberOfPages来显示带有“X页,共Y页”的导航栏...第1页,共10页等。

非常感谢,巴西利奥。就性能而言,这是最好的方法吗?您知道使用此方法将针对 SQL 服务器执行多少个查询吗? - Pablo Santa Cruz
3
Pablo - 示例中的代码将执行2个单独的SQL查询。但是,这并不一定是必须的。您可以使用ToList()将查询结果放入列表中,然后从中获取Count()。这样,您最终只需要一次对数据库的调用。 - Jose Basilio
4
"(int)(totalCount/pageSize)" 是错误的。假设您有5个项目,页面大小为4?页数将是1而不是2。您还需要测试totalCount%pageSize==0是否成立,并根据情况添加另一个单位。 - Andrei Rînea
4
关于页数,我使用了Math.Ceiling方法,代码如下:int numberOfPages = (int) Math.Ceiling((double) totalCount/pageSize);该方法可以将总数除以每页的大小,然后向上取整得到页数。 - Alex Fairchild
这样做有什么好处吗?var Queryobj = (from item in _dc.Items where item.Description.Contains(description)); int totalCount = Queryobj.Count(); ... return QueryObj.Skip((pageIndex - 1) * pageSize).Take(pageSize); 这样会在数据库中运行两次where子句,只返回第一部分的计数,然后返回分页值吗? - Dan
显示剩余2条评论

1
你可以使用 Take 扩展方法:
public IQueryable<Item> FindItemsByDescription(string description, int resultAmount)
{
   return from item in _dc.Items
          where item.Description.Contains(description).Take(resultAmount);
}

你可以更进一步,使用Skip来处理后续的“页面”:
public IQueryable<Item> FindItemsByDescription(string description, int resultAmount, int page)
{
   return from item in _dc.Items
          where item.Description.Contains(description).Skip(resultAmount * page).Take(resultAmount);
}

1
非常感谢您的快速回复。我知道 Take 和 Skip 方法的存在。然而,如果我真的想要进行分页,必须在不进行分页的情况下知道结果的总数。那么,获取这个“总数”的最佳方法是什么? - Pablo Santa Cruz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接