2013-04-29 17 views
22

ho una tabella come questa (Nome tabella: i messaggi):Entity Framework selezionare una delle ogni gruppo per data

+----+--------------------------+-------+------------+ 
| id |   content   | type | date | 
+----+--------------------------+-------+------------+ 
| 0 | Some text    | TypeA | 2013-04-01 | 
| 1 | Some older text   | TypeA | 2012-03-01 | 
| 2 | Some even older texttext | TypeA | 2011-01-01 | 
| 3 | A dog     | TypeB | 2013-04-01 | 
| 4 | And older dog   | TypeB | 2012-03-01 | 
| 5 | An even older dog  | TypeB | 2011-01-01 | 
+----+--------------------------+-------+------------+ 

Usando un'espressione LINQ Voglio trovare il nuovo contenuto di ogni tipo, per cui il risultato dovrebbe essere

Some text | TypeA 
A dog  | TypeB 

Ho provato alcune cose, ma non ha senso indicare le espressioni non funzionanti.

risposta

50

Se vuoi ottenere l'intero Post. Si può provare questo:

var query = Posts.GroupBy(p => p.Type) 
        .Select(g => g.OrderByDescending(p => p.Date) 
           .FirstOrDefault() 
        ) 
+0

Il gruppo viene eseguito prima dell'esecuzione della query o dopo? Quindi estrarrà ogni riga dal db, quindi li raggrupperà o aggiungerà un gruppo per istruzione alla query in modo da tirare solo le righe raggruppate? – Samir

+0

@Samir: Questo è davvero un buon punto. Sembra avere comportamenti diversi a seconda della versione su EF. EF 7 sembra caricare i dati sul client e li raggruppa: https://stackoverflow.com/questions/11564311/sql-to-entity-framework-count-group-by. Il core EF sembra avere il supporto per il gruppo sql da: https://github.com/aspnet/EntityFrameworkCore/pull/9872. Per confermare questo, è possibile utilizzare un profiler per visualizzare la query sql effettiva. –

+0

@Samir: se si utilizza la versione più recente di EF Core e le prestazioni sono accettabili, è possibile considerare questa soluzione anche se la query sql non utilizza il gruppo per (avvolgere il codice in una funzione in modo da poterlo successivamente ridefinire se necessario), sembra che la gente ne abbia tenuto conto e le versioni successive potrebbero supportarlo. Altrimenti, devi scrivere query sql raw. –

2

suppongo è possibile raggruppare i tuoi messaggi righe per tipo e quindi selezionare primo contenuto di scendere ordinati per data di raccolta di questo tipo

from row in Posts 
group row by row.type 
into g 
select new 
{  
    Content = (from row2 in g orderby row2.date descending select row2.content).FirstOrDefault(), 
    Type = g.Key 
} 
+0

Questo sembra funzionare (dopo aver aggiunto a "" e cambiando primo a FirstOrDefault() C'è un modo per ottenere l'intera posta, o ho bisogno di costruirlo in. "seleziona nuovo"? – Todilo

+1

@Todilo Non riesco a testarlo senza modello, quindi mi dispiace per gli errori :) Puoi ottenere il post modificando il risultato di ritorno da row2.content a row2, ma raggruppare è nessary comunque, perché è necessario il più recente contenuto di "OGNI TIPO". Puoi anche provare a ottenere i tipi Distinti, e quindi foreach selezionare select top 1 Post ordinato per data, suppongo che questa query sarebbe più efficiente – Alex

+0

I see. Vado con "manualmente" creato nuovamente il modello, sembra il modo più efficiente per farlo. Grazie mille! – Todilo

1

o utilizzando risultato temporaneo e predicato

var tmp = posts.GroupBy(x => x.type).Select(x => new {x.Key, date = x.Max(g => g.date)).ToArray(); 

var filter = PredicateBuilder.False<Post>(); 

foreach (var item in tmp) 
{ 
    filter = filter.Or(x => x.type == item.Key && x.date == item.date); 
} 

var newestPosts = posts.Where(filter); 
+0

Come l'esempio precedente ha funzionato, non l'ho provato. Non ho mai visto PredicateBuilder ma sembra una caratteristica interessante che dovrei imparare. Grazie. – Todilo

0

Dalla memoria , qualcosa del genere dovrebbe farlo

var data = context.Posts.Group(p => p.Type) 
         .Select(g => new { 
              Type = g.Key, 
              Date = g.OrderByDescending(p => p.Date) 
                .FirstOrDefault() 
             } 

Questo sarebbe gi hai un nuovo tipo anonimo, ma puoi sempre associarlo a una classe

+0

Intendi GroupBy (...) –

Problemi correlati