2014-12-14 19 views
5

Diciamo che voglio classificare il mio database clienti per paese. In SQL vorrei scrivere:Esiste una funzione in Entity Framework che si traduce nella funzione RANK() in SQL?

select CountryID, CustomerCount = count(*), 
     [Rank] = RANK() over (order by count(*) desc) 
from Customer 

Ora voglio scrivere questo in Entity Framework:

var ranks = db.Customers 
    .GroupBy(c => c.CountryID) 
    .OrderByDescending(g => g.Count()) 
    .Select((g, index) => new {CountryID = g.Key, CustomerCount = g.Count, Rank = index+1}); 

ci sono due problemi con questo:

  1. Non funziona. EF lancia un System.NotSupportedException; evidentemente non esiste una traduzione SQL per lo overload of .Select() che utilizza il numero di riga; dovresti mettere tutto in memoria con un .ToList() per poter chiamare questo metodo; e
  2. Anche se si esegue il metodo nella memoria locale, non gestisce le classificazioni uguali nel modo in cui la funzione RANK() fa in SQL, vale a dire che dovrebbero avere un rango uguale e quindi il seguente elemento salta all'ordine originale.

Quindi, come devo fare?

+2

AKAIK Rank() non ha una funzione incorporata in LINQ. Questa risposta utilizza il tuo approccio, ma sembra funzionare per loro: http://stackoverflow.com/a/21035060/7720 o questa domanda ha diverse opzioni. – Romias

+0

@Romias mi hai messo sulla scia per trovare [questa risposta] (http://stackoverflow.com/a/10705535/7850) che ha risolto il mio problema. Per favore sentiti libero di scriverlo come risposta qui così posso darti credito! –

+0

Contento di aiutarti ... Ho inserito il commento come risposta! Grazie! – Romias

risposta

3

AFAIK Rank() non ha una funzione incorporata in LINQ. This answer utilizza il tuo approccio, ma sembra funzionare per loro. Ecco come si può usare:

var customersByCountry = db.Customers 
    .GroupBy(c => c.CountryID); 
    .Select(g => new { CountryID = g.Key, Count = g.Count() }); 
var ranks = customersByCountry 
    .Select(c => new 
     { 
      c.CountryID, 
      c.Count, 
      Rank = customersByCountry.Count(c2 => c2.Count > c.Count) + 1 
     }); 
+0

Grazie! Ho aggiunto del codice in modo che tu possa vederlo applicato. –