This article is currently in the process of being translated into Vietnamese (~96% done).
Limiting data: the Take() & Skip() methods
Từ trước tới giờ chúng ta đã xem nhiều cách làm việc với dữ liệu thông qua LINQ. Giờ là lúc xem xét làm thế nào để giới hạn dữ liệu mà chúng ta làm việc. Điều này đặc biệt hữu ích khi dùng cơ sở dữ liệu vì thường lượng dữ liệu là rất lớn.
Chúng ta sẽ xem xét phương thức Take() và Skip(), và kết hợp chúng, chúng rất tuyệt vời để phân trang trong website. Thực tế, chúng thường dùng cùng nhau nhưng chúng tất nhiên có thter dùng riêng biệt. Phương thức Take() sẽ cho bạn X phần tử từ nguồn dữ liệu, trong khi Skip() sẽ cho phép bạn bỏ qua X phần tử đầu tiên. Một ví dụ đơn giản có dạng như sau:
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);
Chúng ta tạo ra một danh sách tên và sau đó ở đầu ra chúng ta bỏ qua phần tử đầu tiên (Skip(1)) và sau đó chúng ta lấy hai phần tử tiếp theo (Take(2)), về cơ bản chúng ta có hai moddlename trong danh sách.
Basic pagination with Skip() and Take()
Bạn có thể thấy, cả Take() và Skip() rất đơn giản để dùng, nhưng chúng thú vị hơn để minh họa với nhiều dữ liệu hơn, vì vậy hãy xem ví dụ phức tạp hơn như sau:
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!");
}
}
}
Khá nhiều code nhưng hãy nhin qua chúng. Nửa đầu tiên, chúng ta truyền XML Tỉ giá ngoại tệ XML. Việc này cho phép tôi được giới thiệu với bạn về LINQ với XML, phần rất hay trong LINQ. Chúng ta sẽ nói về LINQ với XML trong một bài khác, nhưng bây giờ, chỉ cần biết cách mà chúng ta dùng nó để lấy thông tin từ XML và đưa chúng vào đối tượng năc danh, bao gồm tên và tỉ giá ngoại tệ, chúng ta sẽ dùng sau này.
Chúng ta có nguồn dữ liệu của tỉ giá ngoại tệ trong currencyRateItems. Trong phần sau của ví dụ, chúng ta dùng nguồn để phân trang - chúng ta chỉ đơn giản lấy ra 5 entries và sau đó hỏi người dùng nhấn vào phím nào đó để có 5 nữa (hay phần còn lại trong nguồn). Chúng ta làm vậy bằng cách trích 5 entries đầu tiên và sau đó chúng ta dùng vòng lặp while để tiếp tục đưa ra 5 entries tiếp theo cho tới khi hết dữ liệu. Có 5 entries tiếp theolà sự kết hợp của Skip() và Take().
Summary
Phương thức Skip() và Take() dùng rất đơn giản, tuy nhiên rất hữu ích trong nhiều trường hợp. Như đã đề cập, chúng thường dùng cùng nhau nhưng đặc biệt là phương thức Take() cũng có thể dùng riêng.