2011-02-14 24 views
5

Tôi đã sắp xếp một danh sách các đối tượng với protobuf-net.Lọc hàng loạt với protobuf-net

Về mặt lý thuyết, tệp .bin có thể chứa hàng triệu đối tượng.

Giả sử các đối tượng là một lớp chứa sau:

public string EventName; 

tôi phải mất một truy vấn và tạo ra một danh sách có chứa các đối tượng phù hợp với truy vấn. Cách chính xác để trích xuất các đối tượng phù hợp từ tệp được tuần tự hóa bằng LINQ là gì?

Trả lời

5

Định dạng protobuf là một chuỗi các mục thẳng; bất kỳ cách lập chỉ mục nào theo cách của bạn chỉ có thể được áp dụng riêng. Tuy nhiên, IEnumerable<T> có sẵn; bạn có thể thấy rằng:

var item = Serializer.DeserializeItems<YourType>(source) 
     .First(item => item.Id == id); 

thực hiện công việc độc đáo; điều này:

  • là lazily spooled; mỗi mục được mang lại riêng lẻ, vì vậy bạn không cần một bộ nhớ đầy đủ
  • được đoản mạch; nếu mục được tìm thấy gần bắt đầu, nó sẽ thoát ra kịp thời

Hoặc cho nhiều mục:

var list = Serializer.DeserializeItems<YourType>(source) 
    .Where(item => item.Foo == foo); 

(thêm một ToList để te cuối trên nếu bạn muốn để đệm các mục phù hợp trong bộ nhớ, hoặc sử dụng mà không có một ToList nếu bạn chỉ muốn phân tích cú pháp một lần theo cách chỉ có hướng tới)

+0

Tôi nghĩ giải pháp này rất hay, nhưng mã sẽ có thể trích xuất một số đối tượng phù hợp với truy vấn. –

+0

@Gilad - bạn có thấy cập nhật của tôi với '.Where()' không? –

+0

Cảm ơn bạn rất nhiều, Mark :). Lần nữa. Tôi nên chuyển làm đối số cho "thẻ" trong phương thức DeserializeItems như thế nào? –

0

Rất tiếc, không có. Để sử dụng LINQ, đối tượng của bạn phải triển khai IQueryable<T> hoặc IEnumerable<T>. Trừ khi có một nhà cung cấp LINQ có thể cung cấp một giao diện IQueryable<T> vào file .bin, bạn sẽ có thể sở để:

  • Deserialize tập tin vào bộ nhớ và sử dụng LINQ-to-đối tượng IEnumerable<T>
  • Viết LINQ của bạn nhà cung cấp có thể cung cấp IQueryable<T> (và đây có thể là tùy chọn thực tế duy nhất nếu tệp của bạn là HUGE) có thể xử lý tệp mà không tải toàn bộ nội dung.
+0

Một công việc tốt mà DeserializeItems cung cấp API 'IEnumerable ', sau đó –

+0

@Marc: Nó sẽ xuất hiện như vậy! Tôi đã giả định rằng deserialization sẽ tải toàn bộ tập tin vào bộ nhớ. Rõ ràng là tôi đã sai về điều đó. –

+0

nó sẽ lazily spool chúng ('yield return') từ dòng - lý tưởng để xử lý khối lượng dữ liệu lớn –

0

protobuf có thể cung cấp cho bạn nội dung của các tệp dưới dạng phát trực tuyến IEnumerable<T>, vì vậy bạn có thể dễ dàng thực hiện điều đó. Thật không may tôi không biết làm thế nào phương pháp được gọi là nhưng nó rất dễ dàng để tìm thấy trong các tài liệu.

+0

DeserializeItems –

+0

@Marc Tôi nên serialize các mục để sử dụng DeserializeItems như thế nào? Bạn có ví dụ nhanh ở đâu không?Tôi đang cố gắng để làm điều này chỉ trong V2. – gjvdkamp

+0

Đừng bận tâm tìm ra nó, nó ở trong PrefixStyle.Base128 – gjvdkamp

1

Nếu bạn muốn thêm một số chiếu vào danh sách các phần tử đã chọn, bạn nên thử thư viện của tôi, https://github.com/Scooletz/protobuf-linq. Họ cũng có sẵn trên NuGet. Thư viện làm giảm đáng kể quá trình deserialization. Trong một số trường hợp, nó có thể giảm tới 50% truy vấn ban đầu.