Pergunta

I have an SQL query which I want to call from LINQ to SQL in asp.net application.

SELECT TOP 5 *
FROM   (SELECT SongId,
               DateInserted,
               ROW_NUMBER()
                 OVER(
                   PARTITION BY SongId
                   ORDER BY DateInserted DESC) rn
        FROM   DownloadHistory) t
WHERE  t.rn = 1
ORDER  BY DateInserted DESC 

I don't know whether its possible or not through linq to sql, if not then please provide any other way around.

Foi útil?

Solução

I think you'd have to change the SQL partition to a Linq group-by. (Effectively all the partition does is group by song, and select the newest row for each group.) So something like this:

IEnumerable<DownloadHistory> top5Results = DownloadHistory
    // group by SongId
    .GroupBy(row => row.SongId)

    // for each group, select the newest row
    .Select(grp => 
        grp.OrderByDescending(historyItem => historyItem.DateInserted)
        .FirstOrDefault()
    )

    // get the newest 5 from the results of the newest-1-per-song partition
    .OrderByDescending(historyItem => historyItem.DateInserted)
    .Take(5);

Outras dicas

Although McGarnagle answer solves the problem, but when i see the execution plan for the two queries, it was really amazing to see that linq to sql was really too slow as compare to native sql queries. See the generated query for the above linq to sql:

--It took 99% of the two execution

SELECT TOP (5) [t3].[SongId], [t3].[DateInserted]
    FROM (
        SELECT [t0].[SongId]
        FROM [dbo].[DownloadHistory] AS [t0]
        GROUP BY [t0].[SongId]
        ) AS [t1]
    OUTER APPLY (
        SELECT TOP (1) [t2].[SongId], [t2].[DateInserted]
        FROM [dbo].[DownloadHistory] AS [t2]
        WHERE [t1].[SongId] = [t2].[SongId]
        ORDER BY [t2].[DateInserted] DESC
        ) AS [t3]
    ORDER BY [t3].[DateInserted] DESC


--It took 1% of the two execution
SELECT TOP 5 t.SongId,t.DateInserted
    FROM   (SELECT SongId,
               DateInserted,
               ROW_NUMBER()
                 OVER(
                   PARTITION BY SongId
                   ORDER BY DateInserted DESC) rn
        FROM   DownloadHistory) t
    WHERE  t.rn = 1
    ORDER  BY DateInserted DESC 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top