2012-05-10 4 views
6

Ho una tabella che ha una chiave di 2 parti; una colonna ID e un numero di versione. Sto provando a selezionare 'solo l'ultima versione' dei record.Perché questo gruppo LINQ non è aggregando le righe in vb.net?

Sto provando a utilizzare lo stile di espressione di LINQ, per ottenere un GROUP BY, ed estrarre il valore MAX aggregato della versione. Tuttavia nessuna aggregazione è in corso.

Codice Sintetica:

From C In Credentials 

Group Join .... 
Group Join .... 

Group C.CredentialID, NE.ClientID, C.Version By 
    NE.ClientID, C.CredentialID Into CGroup = Group 
From CG In CGroup 

Select New With { 
    .ClientID = CG.ClientID, 
    .CredentialID = CG.CredentialID, 
    .MaxVersion = CGroup.Max(Function(p) p.Version) 
} 

risultati effettivi:

ClientID CredentialID MaxVersion 
1196  1   3 
1196  1   3 
1196  1   3 
1196  2   1 

risultati desiderati:

ClientID CredentialID MaxVersion 
1196  1   3 
1196  2   1 

provato Inoltre, gli stessi risultati:

Group C By Key = New With 
    {Key NE.ClientID, Key C.CredentialID} Into CGroup = Group 
From CG In CGroup 

Select New With { 
    .ClientID = Key.ClientID, 
    .CredentialID = Key.CredentialID, 
    .MaxVersion = CGroup.Max(Function(p) p.Version) 
} 

Sto cercando una soluzione che non comporta la creazione di classi personalizzate con proprietà di corrispondenza e ordinamento personalizzato/funzioni di raggruppamento, e non utilizza le espressioni lambda sulla coda della query.

Grazie!

risposta

3
From CG In CGroup 

Questa linea chiama Queryable.SelectMany e decomprime i gruppi. Non spacchettare i tuoi gruppi!

Rimuovere quella linea e finire con:

Select New With { 
    .ClientID = CGroup.Key.ClientID, 
    .CredentialID = CGroup.Key.CredentialID, 
    .MaxVersion = CGroup.Max(Function(p) p.Version) 
} 
+0

wow, modo per salvare il giorno –

+0

Posso chiedere dove hai imparato questa importante pepita di informazioni? –

+0

Principalmente dal riversamento sui riferimenti msdn per System.Linq.Enumerable e System.Linq.Queryable. Non abbiate paura di usare la sintassi lambda, il compilatore trasforma comunque ciò che scrivete. –

1

Il problema è che la classe anonima definita per la chiave non valuta l'uguaglianza nel modo che preferisci. Invece, è possibile utilizzare una tupla per la chiave:

From C In Credentials 
... 
Group C.CredentialID, NE.ClientID, C.Version By key = 
     New Tuple(Of Integer, Integer)(NE.ClientID, C.CredentialID) 
     Into CGroup = Group 
Select New With { 
     .ClientID = key.Item1, 
     .CredentialID = key.Item2, 
     .MaxVersion = CGroup.Max(Function(p) p.Version) 
} 
+0

ho ottenuto questo errore in fase di esecuzione e in LINQPad: "Solo i costruttori senza parametri e inizializzatori sono supportati in LINQ to Entities". –

+0

Oh, ho appena provato con Linq2Objects. Ho paura, a meno che tu non voglia abusare di altre classi per quel caso, dovrai creare una piccola classe che possa contenere la chiave. –

+0

Linq agli oggetti è irrilevante. Questa è una query EF. La query viene inviata al database e non valutata con istanze .net. Non ci sono istanze di chiavi di gruppo anonime e la loro semantica di uguaglianza non viene utilizzata. –