Let's say I want to rank my customer database by country. In SQL I would write:
select CountryID, CustomerCount = count(*),
[Rank] = RANK() over (order by count(*) desc)
from Customer
Now I want to write this 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});
There are two problems with this:
System.NotSupportedException
; evidently there's no SQL translation for the overload of .Select()
that uses the row number; you would have to pull everything into memory with a .ToList()
in order to be able to call this method; andRANK()
function does in SQL, i.e. they should have an equal rank, and then the following item skips to the original order.So how should I do this?
AFAIK Rank() has no builtin function in LINQ. This answer uses your approach, but it seems to work for them. Here's how you could use it:
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
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With