2008-12-08 41 views
13

Có thể sử dụng chức năng "phân trang" trong các truy vấn LINQ không? Hãy nói rằng tôi có một số XML như thế này:Câu hỏi thường gặp LINQ: Có phân trang trong các truy vấn LINQ có thể không?

<Root> 
    <BetaSection> 
     <Choices> 
      <SetA> 
       <Choice id="choice1">Choice One</Choice> 
       <Choice id="choice2">Choice Two</Choice> 
       <Choice id="choice3">Choice Three</Choice> 
       . 
       . 
       . 
       <Choice id="choice48">Choice Forty-Eight</Choice> 
       <Choice id="choice49">Choice Forty-Nine</Choice> 
       <Choice id="choice50">Choice Fifty</Choice> 
      </SetA> 
     </Choices> 
    </BetaSection> 
</Root> 

Nếu tôi muốn thực hiện chức năng phân trang, tôi sẽ có thể cung cấp một bù đắp cho một truy vấn LINQ như vậy mà tôi có thể bắt đầu từ yếu tố thứ 11 và kết thúc vào ngày 20 thành phần? Nếu có, truy vấn sẽ khác nếu dữ liệu là danh sách các đối tượng thay vì XML?

+0

phân trang theo LINQ là có thể. tôi không biết những gì u cố gắng đạt được.nếu có các bản ghi khổng lồ được lưu trong tệp xml và bạn muốn tìm nạp dữ liệu từ đó bằng linq với phân trang thì không thể. hầu hết thời gian mọi người sử dụng lớp xml doc để đọc tệp xml và sau đó tải đầy đủ dữ liệu xml vào bộ nhớ. không nên coi là phân trang khi tải dữ liệu đầy đủ vào bộ nhớ. LINQ sẽ chỉ đọc vài dữ liệu từ bộ nhớ và trả về ........ nhưng điều này không thể được gọi là pagination.pagination có nghĩa là tôi sẽ tải chỉ vài dữ liệu vào bộ nhớ mà tôi sẽ hiển thị hoặc làm việc với. – Thomas

Trả lời

18
var q = from X in Choices.Skip((page-1)*pageSize).Take(pageSize) 
     select X; 

Bây giờ, nếu bạn cần một mệnh đề where trong nó, nó được một chút phức tạp hơn:

var q = (from X in Choices 
     where x.SomeField == SomeValue 
     select X).Skip((page-1)*pageSize).Take(pageSize); 
+1

Đối với trường hợp thứ hai của bạn, có lẽ dễ dàng hơn khi chỉ sử dụng các phương thức mở rộng, thay vì trộn theo cú pháp ngôn ngữ: var q = Choices.Where (x => x.SomeField == SomeValue) .Skip ((trang - 1) * pageSize) .Take (pageSize); –

+0

Trong trường hợp đầu tiên bạn có thể xóa 'từ X trong' và' chọn X'. –

+1

Điều này có hiệu quả khi nộp đơn đặt hàng không? Tôi có nghĩa là tôi mong đợi Linq để lần đầu tiên áp dụng orderby và sau đó bỏ qua và mất ... – Andry

2
var pagedData = aDataSource.Skip(20).Take(10); 

Bằng cách đó, bạn đang bỏ qua 20 yếu tố và lấy tiếp 10

1

Các "Đi" và "Bỏ qua" phương pháp khuyến nông cung cấp cho việc này.

myQueryable = myQueryable.Skip(10).Take(10); 
3

Tuyệt đối - Skip()Take() đạt được phân trang, và được hỗ trợ bởi khá-nhiều tất cả Nhà cung cấp LINQ. Trong trường hợp này có vẻ như bạn đang sử dụng LINQ-to-Xml, vì vậy hãy bỏ qua bit sau đây - nhưng để biết thông tin chung: lưu ý rằng nếu dữ liệu đến từ cơ sở dữ liệu thông qua quy trình được lưu trữ, nó là khó trang tại máy chủ. Tuy nhiên, bạn có thể soạn (ví dụ: trang) "UDF". LINQ-to-SQL hỗ trợ UDF (thông qua [FunctionAttribute]), nhưng không hỗ trợ khung thực thể. Nếu bạn đang sử dụng truy vấn cơ sở dữ liệu được tạo tự động thì đây không phải là vấn đề.

Lưu ý rằng với xml, bạn cũng có thể làm được rất nhiều với xpath - đây sử dụng XmlDocument:

foreach (XmlElement el in doc.SelectNodes(
    "/Root/BetaSection/Choices/SetA/Choice[position() > 11 and position() < 20]")) 
{ 
    Console.WriteLine(el.GetAttribute("id")); 
} 

hoặc với Skip()/Take() (vẫn với XmlDocument):

foreach (var el in doc.SelectNodes(
    "/Root/BetaSection/Choices/SetA/Choice").Cast<XmlElement>() 
    .Skip(10).Take(10)) 
{ 
    Console.WriteLine(el.GetAttribute("id")); 
} 
+0

tôi đã thấy mã của bạn nhưng khi chúng tôi làm việc với lớp xmldoc để tải và đọc tập tin xml sau đó đầu tiên tất cả dữ liệu tải vào bộ nhớ. nếu tất cả các dữ liệu tải vào bộ nhớ và chọn vài từ đó với bỏ qua và mất chức năng ...... hiện nó thực sự xem xét như là phân trang? phân trang có nghĩa là tôi sẽ tải chỉ vài dữ liệu vào bộ nhớ mà tôi sẽ hiển thị hoặc làm việc với. – Thomas

1

Có nó là . Bạn sẽ phải có được XML sang một định dạng DataSource thích hợp và sau đó chủ đề này qua trên các diễn đàn MSDN nên cung cấp các bước cần thiết để cung cấp cho bạn khả năng về làm thế nào để thực hiện nó ...

MSDN - LINQ with pagination

3

Đưa xem xét các phương pháp Queryable.SkipQueryable.Take.

Cũng thấy hữu ích extension methods này cho phân trang,

với các phương pháp mà bạn có thể làm điều này như thế này:

List<string> names = new List<string>(); 
names.AddRange(new string[]{"John","Frank","Jeff","George","Bob","Grant", "McLovin"}); 

foreach (string name in names.Page(2, 2)) 
{ 
    Console.WriteLine(name); 
} 
3

James Curran có điều đó đúng, bạn có thể đơn giản hóa điều đó bằng cách tạo ra một phương pháp khuyến nông để tái sử dụng sau này.

Bạn cũng có thể sửa đổi mã để trả lại cho bạn một đối tượng có thể theo dõi tổng số mục trong danh sách và số trang cần dựa trên trangSize và pageIndex.

public static IQueryable<T> ToPageOfList<T>(this IQueryable<T> source, int pageIndex, int pageSize) 
{ 
    return source.Skip(pageIndex * pageSize).Take(pageSize); 
} 

//Example 
var g = (from x in choices select x).ToPageOfList(1, 20); 
Các vấn đề liên quan