I understand that if you have some function in a linq query that does not map to a sql query then you must call .AsEnumerable() first:
var model = _service.GetQuery
.Where(data => data.SomeFlag == true)
.Select(data => new { Foo = CalculateFoo(data.Bar); });
Cannot be executed by linq to sql, but by adding AsEnumerable() we can make the .Select() clause execute by linq to objects instead:
var model = _service.GetQuery
.Where(data => data.SomeFlag == true)
.AsEnumerable()
.Select(data => new { Foo = CalculateFoo(data.Bar); });
But what if the dataset is very large - what affect does AsEnumerable have on paging? If I say:
var page = model.Skip((page > 0 ? page - 1 : 0) * rows).Take(rows);
Because model is now IEnumerable instead of IQueryable, when we say model.Skip().Take(), does it have to first load the entire dataset from the database before it can skip and take? (This would defeat the purpose of paging)
EDIT: The question was written generically - these are the concrete details:
I do not have control over the paging. I am generating a model and passing it to a grid component (DevExpress in this case, but could be any grid). It is the grid component that issues the paging commands. Any solution that involves using .Skip().Take() before AsEnumerable() is not possible here.
So I need to be able to pass this model to the grid, and also at the same time make sure that the model uses deferred execution:
var model = _service.GetQuery
.Where(data => data.SomeFlag == true)
.Select(data => new {
data.Id,
data.Customer.Code,
data.Customer.Name,
// etc, select a few other properties
Foo = CalculateFoo(data.Bar);
});
So now I have a rock vs hard place problem:
If you make paging, you need ...a page, and a total
so
var query= _service.GetQuery
.Where(data => data.SomeFlag == true);
ViewBag.Total = query.Count();
var model = query.Skip((page > 0 ? page - 1 : 0) * rows).Take(rows)
.AsEnumerable()
.Select(data => new { Foo = CalculateFoo(data.Bar); });
Because model is now IEnumerable instead of IQueryable, when we say model.Skip().Take(), does it have to first load the entire dataset from the database before it can skip and take? (This would defeat the purpose of paging)
That's a fact : you shall always have only your "accepted by linq2entites" query before "paging".
EDIT
I do not have control over the paging. I am generating a model and passing it to a grid component (DevExpress in this case, but could be any grid). It is the grid component that issues the paging commands. Any solution that involves using .Skip().Take() before AsEnumerable() is not possible here.
Well, "usually" Grid-systems allow (telerik) (or have only (MvcContrib) custom paging (which means you have to provide the "selected page" results + the total count, as in my answer).
I made a search (you could go further) on "DevExpress custom paging", which give few results. Don't know if they're interesting for you.
Examples of answer