How to get row number via LINQ using Entity framew

2019-08-11 14:34发布

Hope someone can help me out here as I'm a little stuck.

I'm building a service in front of a hiscore database for a game.

The database have the following two tables:

CREATE TABLE [dbo].[PB_HiscoreEntry] (
    [Id]          UNIQUEIDENTIFIER NOT NULL,
    [PlayerId]    UNIQUEIDENTIFIER NOT NULL,
    [Score]       INT              NOT NULL,
    [DateCreated] DATETIME         NOT NULL
);


CREATE TABLE [dbo].[PB_Player] (
    [Id]             UNIQUEIDENTIFIER NOT NULL,
    [UniquePlayerId] NCHAR (32)       NOT NULL,
    [Name]           NVARCHAR (50)    NOT NULL,
    [DateCreated]    DATETIME         NOT NULL
);

The idea is of course to only have each player once in the database and let them have multiple hiscore entries. This table PB_HiscoreEntry will have a lot of scores, but by doing a simple OrderBy descending, I can create a real hiscore list where the one with highest score is at the top and the lowest at the bottom. My problem here is that my database don't have any idea of the actual Rank of the score compared to the others. This is something I should do as I do the OrderBy query described above.

Here is some code to help illutrate what I want to archive:

var q = (
    from he in entities.PB_HiscoreEntry
    orderby he.Score descending
    select new HiscoreItem()
    {
        UserId = he.PB_Player.UniquePlayerId,
        Username = he.PB_Player.Name,
        Score = he.Score,
        //Put in the rank, relative to the other entires here
        Rank = 1 
    });

HiscoreItem, is just my own DTO i need to send over the wire.

So anybody have an idea of how I can do this or am I on a totally wrong path here?

1条回答
孤傲高冷的网名
2楼-- · 2019-08-11 14:38

You're on the right track, you just need to use the Queryable.Select overload that takes an extra index. Take a look at this:

var entries =
    from entry in entities.PB_HiscoreEntry
    orderby entry.Score descending
    select entry;

// Note the (entry, index) lambda here.
var hiscores = entries.Select((entry, index) => new HiscoreItem()
{
    UserId = entry.PB_Player.UniquePlayerId,
    Username = entry.PB_Player.Name,
    Score = entry.Score,
    Rank = index + 1
});

I'm not 100% sure if Entity Framework knows how to work with the Select<TSource, TResult>(this IQueryable<TSource>, Expression<Func<TSource, int, TResult>>) overload. If that's the case, just use the equivalent method of the static Enumerable class:

// Note the .AsEnumerable() here.
var hiscores = entries.AsEnumerable()
    .Select((entry, index) => new HiscoreItem()
{
    UserId = entry.PB_Player.UniquePlayerId,
    Username = entry.PB_Player.Name,
    Score = entry.Score,
    Rank = index + 1
});

I hope this helps.

查看更多
登录 后发表回答