2014-12-14 28 views
5

Załóżmy, że chcę uszeregować bazę danych klientów według krajów. W SQL chciałbym napisać:Czy istnieje funkcja w Entity Framework, która przekłada się na funkcję RANK() w SQL?

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

Teraz chcę napisać to w 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}); 

Istnieją dwa problemy z tym:

  1. to nie działa. EF wyrzuca System.NotSupportedException; ewidentnie nie ma tłumaczenia SQL dla overload of .Select(), który używa numeru wiersza; musiałbyś wciągnąć wszystko do pamięci za pomocą .ToList(), aby móc wywołać tę metodę; i
  2. Nawet jeśli uruchomisz tę metodę w pamięci lokalnej, nie obsługuje ona jednakowych rankingów w taki sposób, jak funkcja RANK() w SQL, to znaczy powinna mieć równą pozycję, a następna pozycja przechodzi do pierwotnej kolejności.

Jak powinienem to zrobić?

+2

AKAIK Rank() nie ma funkcji wbudowanej w LINQ. Ta odpowiedź wykorzystuje twoje podejście, ale wydaje się, że działa dla nich: http://stackoverflow.com/a/21035060/7720 lub to pytanie ma kilka opcji. – Romias

+0

@Romias ustawiasz mnie na szlaku, aby znaleźć [tę odpowiedź] (http://stackoverflow.com/a/10705535/7850), która rozwiązała mój problem. Proszę napisać to jako odpowiedź tutaj, więc mogę dać ci kredyt! –

+0

Cieszę się, że mogę ci pomóc ... Umieściłem komentarz jako odpowiedź! Dzięki! – Romias

Odpowiedz

3

Pozycja AFAIK() nie ma funkcji wbudowanej w LINQ. This answer wykorzystuje twoje podejście, ale wydaje się, że działa dla nich. Oto, jak możesz go użyć:

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

Dzięki! Dodałem kod, dzięki czemu możesz go zobaczyć. –