2011-10-26 9 views
10

per scopi didattici ho cercato di convertire la seguente espressione Linq dal libro "Linq in azione" in VB.netLinq non lo fa gruppo in VB.Net

Original 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 
    }; 

Il mio tentativo:

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 

Questo porta alla seguente output:

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 

Mi aspettavo che i libri "LINQ rules" e "C# on rails" fossero raggruppati così come i libri "Funny Stories" e "Bonjour mon Amour" perché hanno lo stesso editore e soggetto. La mia chiave anonima è costituita da un nuovo oggetto costituito da due semplici stringhe.

Ho già provato a cercare in SO, ma le risposte other (or) non risolvono il mio problema. Anche alcuni traduttori di codici come telerik o carlosag non sono di aiuto in questo caso.

risposta

7

Questo è il problema:

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

Questo non è equivalente alla versione C#, perché purtroppo VB utilizza mutabili immobili a tipi anonimi per impostazione predefinita e le proprietà mutevoli non sono considerati come parte del hash operazioni di codice o di uguaglianza. È necessario effettuare entrambe le proprietà Proprietà "Chiave":

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

Quindi dovrebbe funzionare correttamente. Puoi leggere ulteriori informazioni sui tipi anonimi in VB on MSDN.

+1

Si Questa grande opera; molte grazie! Wow, una risposta di Jon Skeet stesso. Mi sento onorato. :-) – Markus

+0

Ho verificato la mia query non riuscita a causa di questo in LINQPad e ho utilizzato una fonte LINQ to Entities. Nel mio codice sto effettivamente materializzando la query (ToList) e eseguendo la query di gruppo da quella in quanto devo fare alcuni calcoli per riga nel frattempo. Questo mi porta a credere che questo sia un problema in LINQ to Objects ma non LINQ to Entities. Suppongo che ciò avverrebbe perché in LINQ alle Entità, l'espressione di raggruppamento è tradotta in TSQL mentre in LINQ agli Oggetti, il codice hash viene utilizzato per l'uguaglianza delle chiavi di gruppo. Questo suono è corretto? – pseudocoder

+0

@pseudocoder: No, non si tratta del codice hash, ma di quali proprietà vengono utilizzate per determinare l'uguaglianza. Sembra che LINQ to Entities consideri * tutte * le proprietà come proprietà chiave ... che suona come un bug per me. Questo non è un "problema" in LINQ to Objects: è solo questione di come funzionano i tipi anonimi in VB. –

5

Mentre applaudo i vostri sforzi per tradurre gli esempi, in realtà abbiamo tutti i campioni per LINQ in Azione in C# e VB disponibili per il download dal sito di Manning: http://www.manning.com/marguerie/. Inoltre, abbiamo aggiunto campioni ai campioni LinqPad per semplificare la prova dei campioni e il salvataggio delle modifiche. Vedi http://www.thinqlinq.com/Default/LINQ-In-Action-Samples-available-in-LINQPad.aspx per le istruzioni su come accedervi.

Sembra che si stia lavorando all'esempio 5.06b. Aggiornamento leggermente, la nostra traduzione VB è:

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 

Se si desidera utilizzare la sintassi Lambda, si ha bisogno di specificare la chiave come @johnskeet indicati:

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, e lo stesso autore ... :-) Grazie per i collegamenti linq e i frammenti di codice. – Markus