2011-10-26 26 views
10

Para los fines educativos que trataron de convertir la siguiente expresión LINQ del libro "Linq en acción" en VB.netLINQ no lo hace el grupo en VB.Net

C# original

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

Mi intento:

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 

Esto lleva a la siguiente salida:

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 

Espero que los libros "LINQ rules" y "C# on rails" estén agrupados, así como los libros "Funny Stories" y "Bonjour mon Amour" porque tienen el mismo Publisher and Subject. Mi clave anónima consiste en un nuevo objeto de dos cadenas simples.

Ya he intentado buscar en SO, pero other (or) las respuestas no resuelven mi problema. Incluso algunos traductores de código como telerik o carlosag no son de ayuda en este caso.

Respuesta

7

Este es el problema:

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

Eso no es equivalente a la versión C#, porque por desgracia VB utiliza mutables propiedades en los tipos anónimos por defecto, y las propiedades mutables no se considera como parte del hash operaciones de código o igualdad. Necesita hacer que ambas propiedades propiedades "Clave":

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

Entonces debería funcionar bien. Puede leer más acerca de los tipos anónimos en VB on MSDN.

+1

Si esto funciona muy bien; ¡muchas gracias! Guau, una respuesta del propio Jon Skeet. Me siento honrado. :-) – Markus

+0

Probé mi consulta que estaba fallando debido a esto en LINQPad y utilicé un LINQ para el origen de Entidades. En mi código, en realidad estoy materializando la consulta (ToList) y ejecutando la consulta de grupo, ya que tengo que hacer algunos cálculos por filas entre tanto. Esto me lleva a pensar que esto es un problema en LINQ to Objects pero no LINQ to Entities. Supongo que esto se debe a que en LINQ to Entities, la expresión de agrupación se traduce a TSQL, mientras que en LINQ to Objects, el código hash se utiliza para la igualdad de clave de grupo. ¿Esto suena correcto? – pseudocoder

+0

@pseudocoder: No, no se trata del código hash, sino de qué propiedades se usan para determinar la igualdad. Suena como LINQ to Entities trata * todas las propiedades * como propiedades clave ... lo que me suena como un error. Esto no es un "problema" en LINQ to Objects; solo se trata de cómo funcionan los tipos anónimos en VB. –

5

Si bien aplaudo sus esfuerzos para traducir las muestras, en realidad tenemos todas las muestras para LINQ in Action en C# y VB disponibles para su descarga desde el sitio de Manning: http://www.manning.com/marguerie/. Además, hemos agregado muestras a las muestras de LinqPad para que sea más fácil probar las muestras y guardar sus cambios. Consulte http://www.thinqlinq.com/Default/LINQ-In-Action-Samples-available-in-LINQPad.aspx para obtener instrucciones sobre cómo acceder a eso.

Parece que está trabajando en el ejemplo 5.06b. Actualizándolo poco, nuestra traducción VB es:

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 

Si desea utilizar la sintaxis lambda, que es necesario especificar la clave como @johnskeet informativo:

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, y el autor mismo ... :-) Gracias por los linq-links y los fragmentos de código. – Markus