This article is currently in the process of being translated into Chinese (~90% done).
Limiting data: the Take() & Skip() methods
到目前为止,在本教程的 LINQ 章节中,我们已经了解了几种使用 LINQ 处理数据源的方法。 现在,也是时候去看下如何获取部分的数据。这使用数据库作为数据源时极其有用,因为它通常涉及到海量的需要获取的数据行。
本文中所将讨论的主要涉及到的方法是 Take() 方法和 Skip() 方法,并且他们相互结合非常适合网站上的分页操作。实际上,它们也通常一起使用,但他们也能够分开使用。Take() 方法会从数据源中取出 X 个数据项,而 Skip() 方法会直接跳过前 X 个数据项。下面是一个简单的例子:
List<string> names = new List<string>()
{
"John Doe",
"Jane Doe",
"Joe Doe",
"Jenna Doe",
};
var middleNames = names.Skip(1).Take(2).ToList();
foreach (var name in middleNames)
Console.WriteLine(name);
这里,我们创建了一个简单的名字列表,然后,我们跳过第一个名字(Skip(1))然后获取接下来的两个名字(Take(2)),最后输出列表中中间的两个名字。
使用 Skip() 和 Take() 进行基础分页
如你所见,Take() 和 Skip() 方法都是非常易于使用的,但是使用比之前所使用的数据的话会发现他们更加有趣。因此,这里,我自由地创建了一个稍微更加复杂的例子,该例子能够更好地说明这些方法是如何帮到你。首先,代码如下:
using System;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
namespace LinqTakeSkip1
{
class Program
{
static void Main(string[] args)
{
CultureInfo usCulture = new CultureInfo("en-US");
XDocument xDoc = XDocument.Load("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
var cubeNodes = xDoc.Descendants().Where(n => n.Name.LocalName == "Cube" && n.Attribute("currency") != null).ToList();
var currencyRateItems = cubeNodes.Select(node => new
{
Currency = node.Attribute("currency").Value,
Rate = double.Parse(node.Attribute("rate").Value, usCulture)
});
int pageSize = 5, pageCounter = 0;
var pageItems = currencyRateItems.Take(pageSize);
while(pageItems.Count() > 0)
{
foreach (var item in pageItems)
Console.WriteLine(item.Currency + ": " + item.Rate.ToString("N2", usCulture));
Console.WriteLine("Press any key to get the next items...");
Console.ReadKey();
pageCounter++;
// Here's where we use the Skip() and Take() methods!
pageItems = currencyRateItems.Skip(pageSize * pageCounter).Take(pageSize);
}
Console.WriteLine("Done!");
}
}
}
这里的代码有一点多,但是让我一点点来看。在上半部分,我们解析了一个公开的 XML 货币汇率源。这让我有机会简要地介绍下 LINQ to XML,它也是 LINQ 生态系统中的一个非常酷的部分。我们会在另一篇文章中讨论 LINQ to XML,但是现在,我们只需要知道我们使用它从 XML 源中提取重要节点并将其放在匿名对象中,该匿名对象包含了货币名称以及其当前的汇率,我们之后再使用它。
现在,我们在 currencyRateItems 变量中存储了一个非常好的货币信息数据源。在例子的后半段中,我们使用该数据源进行一些简单的分页。我们只需要先提取出 5 个数据项然后要求用户按一个键来获取下5个数据项(或者是数据源中剩下来的所有数据项)。为了达到这个目的,我们获取前5个数据项然后使用 while 循环连续获取下 5 个数据项,直到数据源为空。我们通过结合 Skip() 方法和 Take() 方法来实现获取后面 5 个数据项,这也是整篇文章的全部基础。
概括
Skip() 和 Take() 方法使用起来非常简单,然而在很多情况下也非常有用。如上所述,他们通常结合在一起使用,但是尤其是 Take() 方法可以分开使用。