5

I have a query with a left join in it:

   var query = (from v in context.Vehicles

                //left join vehicleAttributes
                join va in context.VehicleAttributes on v.VehicleId equals va.VehicleId into vAttributes
                from vehicleAttributes in vAttributes.DefaultIfEmpty()

                where v.FleetId == fleetId

                select new { v, vehicleAttributes });

And now I need to do a paging on it.

this works but gets all rows, so much more than i actually need

query.ToList().Select(x => x.v).Distinct().Skip(10 * (page - 1)).Take(10).ToList();

this is what I tried instead but now I don't have the joint values

query.Select(x => x.v).Distinct().ToList().Skip(10 * (page - 1)).Take(10).ToList();

any ideas?

Thanks

qxn
  • 17,162
  • 3
  • 49
  • 72
Timothy
  • 608
  • 3
  • 10
  • 24

2 Answers2

7

The ToList() triggers the call to the database so you need to only do this after you apply the Skip and Take. You'll need an OrderBy clause as well.

You should be able to do something like this:

var data = (from v in context.Vehicles
         join va in context.VehicleAttributes on v.VehicleId equals va.VehicleId into vAttributes
         from vehicleAttributes in vAttributes.DefaultIfEmpty()
         where v.FleetId == fleetId
         select new { v, vehicleAttributes })
         .OrderBy(p => p.v.FleetId)
         .Skip(10 * (page - 1))
         .Take(10)
         .ToList();
Sean Kenny
  • 1,626
  • 13
  • 14
  • 1
    yes I know that ToList() calls the database but how do I solve this? I tried this: query.Select(x => x.v).Distinct().ToList().Skip(10 * (page - 1)).Take(10).ToList(); but then I won't get the joint values because I get more than one row per vehicle because it has many attributes... – Timothy Jun 11 '13 at 18:35
0

Don't call ToList before Skip. Doing so will return all the records in the database that match your query.

To use Skip on an EntityFramework query, you need to have an instance of IOrderedQueryable, so you need an OrderBy clause.

query
    .Select(x => x.v)
    .Distinct()
    .OrderBy(v => v.FleetId)
    .Skip(10 * (page - 1))
    .Take(10).ToList();

I've got a project that takes care of a lot of this functionality. It's available on NuGet (with an MVC counterpart) and Google Code.

Using it would look something like this:

var factory = new Pagination.PageSourceFactory {
    MaxItemsPerPage = 50,
    DefaultItemsPerPage = 20
};
var source = factory.CreateSource(query, page);
qxn
  • 17,162
  • 3
  • 49
  • 72
  • Thanks for your answer but your suggestion doesn't work because I get more then one row per vehicle because of the join... If I do what you said I won't get the joint values... – Timothy Jun 11 '13 at 18:38