2011-06-10 20 views
9

Pasé mucho tiempo con este problema. Soy capaz de hacer sencilla Grupo Por consultas LINQ (en una sola propiedad) pero para múltiples campos que estoy un poco atascado ... Aquí es una muestra LINQPad de lo que quiero hacer:LINQ Group by con propiedades múltiples en VB.Net

dim lFinal={new with {.Year=2010, .Month=6, .Value1=0, .Value2=0}, 
      new with {.Year=2010, .Month=6, .Value1=2, .Value2=1}, 
      new with {.Year=2010, .Month=7, .Value1=3, .Value2=4}, 
      new with {.Year=2010, .Month=8, .Value1=0, .Value2=1}, 
      new with {.Year=2011, .Month=1, .Value1=2, .Value2=2}, 
      new with {.Year=2011, .Month=1, .Value1=0, .Value2=0}} 

Dim lFinal2 = From el In lFinal 
       Group el By Key = new with {el.Year,el.Month} 
       Into Group 
       Select New With {.Year = Key.Year, .Month=Key.Month, .Value1 = Group.Sum(Function(x) x.Value1), .Value2 = Group.Sum(Function(x) x.Value2)} 

lFinal.Dump() 
lFinal2.Dump() 

El lFinal la lista tiene 6 elementos, quiero que lFinal2 tenga 4 elementos: 2010-6 y 2011-1 deben agruparse.

Gracias de antemano.

+0

I also ha d implementar el GetHashCode() para que funcione. – Maher

Respuesta

4

No es 100% seguro, pero probablemente por grupo utiliza los Iguales() y/o GetHashCode aplicación, por lo que cuando lo hace la creación implícita:

= Group el By Key = new with {el.Year,el.Month} 

el objeto implícito no se sabe para comprobar tanto el año y mes (solo porque tiene las propiedades no significa que las verifique cuando se compara con otros objetos).

Así que es probable que tengas que hacer algo más como esto:

= Group el By Key = new CustomKey() { Year = el.Year, Month = el.Month }; 

public class CustomKey{ 
    int Year { get; set; } 
    int Month { get; set; } 

    public override bool Equals(obj A) { 
     var key (CustomKey)A; 
     return key.Year == this.Year && key.Month == this.Month; 
    } 
} 
+0

+1. Si bien la sintaxis del OP funcionará bien con LINQ-to-SQL, producirá el resultado actual cuando se utilice en LINQ-to-Objects. –

+1

+0 Aunque esto es correcto, la palabra clave 'Key' es la respuesta correcta. –

5

Gracias! Pero noté que también necesitaba escribir la función GetHashCode para que funcione. Proporciono la traducción en VB.Net de la clase final + LINQ GroupBy:

Clase:

Public Class YearMonth 
    Implements IEquatable(Of YearMonth) 

    Public Property Year As Integer 
    Public Property Month As Integer 

    Public Function Equals1(other As YearMonth) As Boolean Implements System.IEquatable(Of YearMonth).Equals 
     Return other.Year = Me.Year And other.Month = Me.Month 
    End Function 

    Public Overrides Function GetHashCode() As Integer 
     Return Me.Year * 1000 + Me.Month * 100 
    End Function 
End Class 

Y la consulta LINQ:

Dim lFinal2 = From el In lFinal 
       Group el By Key = New YearMonth With {.Year = el.Year, .Month = el.Month} 
       Into Group 
       Select New ItemsByDates With {.Year = Key.Year, 
              .Month = Key.Month, 
              .Value1 = Group.Sum(Function(x) x.Value1), 
              .Value2 = Group.Sum(Function(x) x.Value2)} 
+1

+0 Aunque esto es correcto, la palabra clave 'Key' es la respuesta correcta. –

18

que las propiedades del tipo anónimo inmutable con el Key palabra clave y luego se usarán para las comparaciones

Dim lFinal2 = From el In lFinal    
    Group el By Key = new with {key el.Year, key el.Month} 
    Into Group 
    Select New With { 
      .Year = Key.Year, 
      .Month = Key.Month, 
      .Value1 = Group.Sum(Function(x) x.Value1), 
      .Value2 = Group.Sum(Function(x) x.Value2) 
    }