简体   繁体   中英

Linq - how to get top records?

I have this code which queries a database

var buildInfoList = (from m in context.BuildInfoes
                     where m.ManagerInfoGuid == managerGuid
                     select m).Take(3).ToList();

the code above gives me the first 3 results, how can i change it to take the last 3?

meaning if i have 100 rows in the database, i want to get 98, 99, 100 and not 1, 2, 3

Reverse the order of the query. The basic idea is reverse the order of the entire query, fetch the first three elements, then reverse the order again to put them back in the right order:

var query = from m in context.BuildInfoes
            where m.ManagerInfoGuid == managerGuid
            select m;
var lastItems = query.OrderByDescending(x => x.ID).Take(3).Reverse().ToList();

PS: If you were using Linq to Objects (but I guess you aren't) you could use TakeLast from morelinq.

Your are not introducing any order here, so you currently get any 3 results which by chance don't happen to be the ones you want. Establish an order:

var buildInfoList = (from m in context.BuildInfoes
                     where m.ManagerInfoGuid == managerGuid
                     orderby m.Name descending
                     select m).Take(3).ToList();

Using orderby you can specify ascending or descending to reverse the order, which will result in returning the first or last 3 elements using Take .

You can use orderby

var buildInfoList = (from m in context.BuildInfoes
                     where m.ManagerInfoGuid == managerGuid
                     orderby m.Id descending
                     select m).Take(3).ToList();

Or, as @MarkByers said, just use Reverse

var buildInfoList = from m in context.BuildInfoes
                    where m.ManagerInfoGuid == managerGuid
                    select m;
var count = buildInfoList.Count();
var list = buildInfoList.Skip(count < 3 ? count - 3 : 0).Take(3).ToList();

edit: Why is this solution different than the others? But this doesn't mean is the best one.

First the OP states that the query is over a database and since the query uses Take without specifying the order, I guess is about Linq To Sql.

This solution is not actually the best because it does two queries, one for the count and the other for to get the items. This solution uses only the SQL to get the last 3 items and doesn't do an order over objects.

While testing it with LINQ Pad I noticed that, when no order is specified, LINQ to SQL generates the order over all the columns

   SELECT ROW_NUMBER() OVER (ORDER BY [t0].[id], [t0].[A], [t0].[B], [t0].[C])

Obs.:

The Reverse method is not translated, so is good to be called after a ToList() call

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM