2011-10-26 39 views
10

Đối với mục đích giáo dục tôi đã cố gắng để chuyển đổi biểu thức LINQ sau từ cuốn sách "LINQ trong hành động" vào VB.netLINQ không nhóm trong VB.Net

gốc C#

var list = 
    from book in SampleData.Books 
    group book by new { book.Publisher.Name, book.Subject } 
    into grouping 
    select new { 
    Publisher = grouping.Key.Publisher, 
    Subject = grouping.Key.Subject, 
    Book = grouping 
    }; 

nỗ lực của tôi:

Dim list = _books.GroupBy(Function(book) New With {.Publisher = book.Publisher.Name, 
                book.Subject}). 
        Select(Function(grouping) New With {.Publisher = grouping.Key.Publisher, 
                 .Subject = grouping.Key.Subject, 
                 .Books = grouping}) 

For Each item In list 
    Console.WriteLine("Publisher:" & item.Publisher & ", Subject:" & item.Subject) 
    For Each Book In item.Books 
    Console.WriteLine(" " & Book.Title) 
    Next 
Next 

Điều này dẫn đến kết quả như sau:

Publisher:FunBooks, Subject:Fun 
    Funny Stories 
Publisher:Joe Publishing, Subject:Work 
    LINQ rules 
Publisher:Joe Publishing, Subject:Work 
    C# on rails 
Publisher:Joe Publishing, Subject:Fun 
    All your base are belong to us 
Publisher:FunBooks, Subject:Fun 
    Bonjour mon Amour 

Tôi mong đợi, sách "Quy tắc LINQ" và "C# trên đường ray" được nhóm cũng như sách "Truyện cười" và "Bonjour mon Amour" vì chúng có cùng Nhà xuất bản và Chủ đề. Khóa ẩn danh của tôi bao gồm một đối tượng mới gồm hai chuỗi đơn giản.

Tôi đã cố gắng tìm kiếm trong SO, nhưng other (or) câu trả lời không giải quyết được sự cố của tôi. Ngay cả một số dịch giả mã như telerik hoặc carlosag không có trợ giúp trong trường hợp này.

Trả lời

7

Đây là vấn đề:

GroupBy(Function(book) New With {.Publisher = book.Publisher.Name, 
            book.Subject}) 

Đó không phải là tương đương với phiên bản C#, vì không may VB sử dụng mutable tài sản trong các kiểu nặc danh theo mặc định, và các tài sản có thể thay đổi không được coi là một phần của băm mã hoặc hoạt động bình đẳng. Bạn cần phải tạo cả thuộc tính "Khóa" cho thuộc tính:

GroupBy(Function(book) New With {Key .Publisher = book.Publisher.Name, 
           Key book.Subject}) 

Sau đó, nó sẽ hoạt động tốt. Bạn có thể đọc thêm về các loại vô danh trong VB on MSDN.

+1

Có này hoạt động tuyệt vời; cảm ơn rất nhiều! Wow, một câu trả lời của Jon Skeet. Tôi cảm thấy vinh dự. :-) – Markus

+0

Tôi đã thử nghiệm truy vấn của mình đã thất bại do điều này trong LINQPad và tôi đã sử dụng nguồn LINQ to Entities. Trong mã của tôi, tôi thực sự hiện thực hóa truy vấn (ToList) và chạy truy vấn nhóm từ đó vì tôi phải thực hiện một số tính toán cho mỗi hàng trong thời gian tạm thời. Điều này khiến tôi tin rằng đây là một vấn đề trong LINQ to Objects chứ không phải LINQ to Entities. Tôi giả định điều này sẽ là vì trong LINQ to Entities, biểu thức nhóm được dịch sang TSQL trong khi trong LINQ to Objects, mã băm được sử dụng cho nhóm bình đẳng chính. Điều này có đúng không? – pseudocoder

+0

@pseudocoder: Không, nó không phải về mã băm - đó là về những thuộc tính được sử dụng để xác định sự bình đẳng. Có vẻ như LINQ to Entities xử lý * tất cả các thuộc tính * như các thuộc tính chính ... có vẻ như là một lỗi đối với tôi. Đây không phải là một "vấn đề" trong LINQ to Objects - nó chỉ là vấn đề làm thế nào các loại vô danh trong VB làm việc. –

5

Trong khi tôi hoan nghênh những nỗ lực của bạn để dịch các mẫu, chúng tôi thực sự có tất cả các mẫu cho LINQ trong hành động trong C# và VB có sẵn để tải xuống từ trang web Manning: http://www.manning.com/marguerie/. Ngoài ra, chúng tôi đã thêm mẫu vào mẫu LinqPad để dễ dàng thử các mẫu và lưu các thay đổi của bạn. Xem http://www.thinqlinq.com/Default/LINQ-In-Action-Samples-available-in-LINQPad.aspx để biết hướng dẫn về cách truy cập.

Dường như bạn đang làm việc trên ví dụ 5.06b. Cập nhật nó một chút, dịch VB của chúng tôi là:

Dim query = _ 
    From book In SampleData.Books _ 
    Group book.Title By book.Publisher, book.Subject Into grouping = Group _ 
    Select _ 
    Publisher = Publisher.Name, _ 
    Subject = Subject.Name, _ 
    Titles = grouping 

Nếu bạn muốn sử dụng cú pháp Lambda, bạn cần phải xác định chính là @johnskeet chỉ:

Dim list = SampleData.Books.GroupBy(Function(book) New With { 
          Key .Publisher = book.Publisher.Name, 
          Key .Subject = book.Subject}). 
       Select(Function(grouping) New With { 
        .Publisher = grouping.Key.Publisher, 
        .Subject = grouping.Key.Subject, 
        .Books = grouping}) 
+0

Ok, và bản thân tác giả ... :-) Cảm ơn linq-links và đoạn mã. – Markus