I have a jqgrid where the database table has a few thousand rows, but the jqrid shows only 15 at a time.
It should be displaying very quickly (it doesnt take long to query 15 rows). But instead it takes 10 - 20 seconds, which indicates to that it is retrieving the entire table each time.
The grid is defined like this:
$("#Products").jqGrid({
url: url, mtype: "get", datatype: "json", jsonReader: {
root: "Rows", page: "Page", total: "Total", records: "Records", repeatitems: false,
userdata: "UserData",id: "Id"},
colNames: ["Product Id","Product Code", ... etc ],
colModel: [{ name: "Id", ... etc}],
viewrecords: true, height: 400, width: 800, pager: $("#jqgPager"),
rowNum: 15, rowList: [50, 100, 200],
autowidth: true, multiselect: false
And the server side (MVC2 action) does this:
var model = (from p in products
select new
{
p.Id, p.ProductCode, p.ProductDescription,
AllocatedQty = p.WarehouseProducts.Sum(wp => wp.AllocatedQuantity),
QtyOnHand = p.WarehouseProducts.Sum(wp => wp.OnHandQuantity)
}).AsQueryable();
JsonResult json = Json(model.ToGridData(
page, rows, orderBy, "",
new[] { "Id", "ProductCode", "ProductDescription", "AllocatedQty", "QtyOnHand" }),
JsonRequestBehavior.AllowGet);
And finally the model.ToGridData extension method does this:
var data =_service.GetAll();
var page = data.Skip((index) * pageSize).Take(pageSize);
list.Add(page.AsEnumerable);
And I'm a bit lost as to where the problem lies:
- Have I set the jqgrid paging options incorrectly?
- Have I written bad Linq that pulls all rows regardless? eg does the Sum() cause all rows to be read?
- Have I done the .Skip().Take() incorrectly?
- Have I missed something else entirely?
EDIT
When comparing my code to the example posted by Oleg I can see that I do things in this order:
- getAll
- select model fields
- page
Wheras Olegs sample seems to be in this order:
- getAll
- page
- select model fields
So I've changed to this much simpler implementation:
public ActionResult GetProductList(int page, int rows, string sidx, string sord,
string searchOper, string searchField, string searchString)
{
List<Product> products = _productService.GetAllProducts();
int totalRecords = products.Count();
var pagedData = products.Skip((page > 0 ? page - 1 : 0) * rows).Take(rows);
var model = (from p in pagedData
select new
{
p.Id, p.ProductCode, p.ProductDescription,
Barcode = string.Empty, UnitOfMeasure = string.Empty,
p.PackSize, AllocatedQty = string.Empty,
QtyOnHand = string.Empty }).ToList();
var jsonData = new
{
total = page, records = totalRecords,
page = (totalRecords + rows - 1) / rows, rows = model
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
However this has a new problem:
A circular reference was detected while serializing an object of type
'System.Data.Entity.DynamicProxies.Product_FA935D3899E2...
The only difference I can see now with Oleg's sample is that his getAll returns IQueryable
where mine is just List
.