I have a .aspx search screen that displays the results of the search in an asp:GridView component. There can be up to approx 1000 records returned by the search. I want to implememt paging on the grid so that only 15 records are displayed at any one time and the user can page through the results.
I am retrieving the records by passing search parameters to a WCF service which returns a List of particular entity objects. I create a Datatable and insert one DataRow per entity object from the List. I then bind the grid view to the Datatable.
This is how my grid is defined in the .aspx page:
<asp:GridView ID="gridCat" runat="server" AutoGenerateColumns="False" DataKeyNames="CatalogueID"
HeaderStyle-CssClass="fieldHeading" RowStyle-CssClass="fieldContent"
AlternatingRowStyle-CssClass="alternateFieldContent" Width="100%"
AllowPaging="True" AllowSorting="True" AutoGenerateDeleteButton="True"
PageSize="15">
and I also have this method in the code behind (.aspx.vb file):
Sub GridPagingAction(ByVal sender As Object, ByVal e As GridViewPageEventArgs) Handles gridCat.PageIndexChanging
gridCat.PageIndex = e.NewPageIndex
gridCat.DataBind()
gridCat.Visible = True
End Sub
My problem is this: the first page is rendered correctly i.e. the first 15 records are displayed correctly. However, when I navigate to page 2 in the grid, the GridPagingAction method is hit on the server but nothing is displayed in the grid - it is just blank.
I think the reason this is happening is because the Datatable no longer exists on the server when the request for the second page hits the server - is that right? And the asp:GridView, when it is rendering the first page of results, only takes the first 15 records from the Datatble and sends them back to the browser. So when the request for the second page comes in the other records (i.e. records 16 - 1000) don't exist anywhere - is all that correct?
If so, what's the best solution - I can't see how to implement paging without having to do one of the following:
re-perform the search each time the user uses the paging option;
saving the search results on the Session after the first Search retrieving them each time the user uses the paging option;
manually inserting the Search results into ViewState and retrieving them each time the user uses the paging option.
Is there a better way to do this (or am I doing it wrong)? If not, which of the 3 options do you think is the best? I'm leaning towards option 2 as I don't think option 1 is performant and I don't want to be sending loads of unnecessary data back to the browser as per option 3.
All you said is correct. You could either use ViewState or the Session to keep hold of the data on client- or server-side, but if you really have that many records, it might be a good idea to only collect the data you actually need.
So if you want to show records 1 to 10, you perform a query against the database and only fetch those ten records. If you want to show the next ten, you perform another query with the according parameters.
This will improve your performance and memory usage significantly, IF calling your DB is not overly expensive.
This article might give you a start on how to do this:
http://dotnetslackers.com/articles/gridview/Optimized-Paging-and-Sorting-in-ASP-NET-GridView.aspx
If you want an easy solution without any additional efforts, I would query all the records on each postback (your option #1).
If you want the best performing solution with not much overhead, use the custom paging.
Related
Right now my website(ASP.NET) has a database where it pulls data from, and the more data enter the longer the page. I am wondering how I can make it so for example once it pulls ten items from database it starts a new page and puts ten more items on the next. Basically like how http://fmylife.com does it.
Thanks
You should take a look att the DataPager Control.
To create a solution that works in the long run, you need to let the paging selection end up in your sql where clause, so that you only retreive the amount of records that you have specified in the PageSize property of the DataPager Control each time you round trip to the database. Otherwise it will lose it's performace when the records in the database increases.
I have a gridview which was working fine with a small dataset in development. In production it has to bind to thousands of records, which is making it slower to load. Is there a way to improve performance, like retrieving the data during gridview pageindex changing?
Also chances are you only want to bind it once. So you should (if not already):
if(!IsPostback)
{
DatabindGridLogicHere();
}
This way your GridView will only have to hit the db the first time to get the data.
First and formost turn off ViewState.
You should tell your datasource to take less records and then enable paging in your grid and datasource.
You can enable "AllowPaging" property to true in your GridView and give a page size say 10. Then Write your data retrieval logic to return a batch of data instead of the whole set of data at once.
When you write the SQL query make sure to order it by an ID.
Thus if the page index is 1 you can take the first batch of data by passing page index of 1 and the page size of 10.
Logic will be;
SELECT [RequiredFields]
FROM [YourDataSource]
WHERE (Id>=((PageIndex-1)*pageSize) AND Id<(PageSize*pageIndex)) ORDER BY Id
In the first page it will return first set of entries of those Ids starting from 0 to 9. In the second page it returns entries of those Ids starting from 10 to 19 assuming the pageSize is 10. You can change the page size and the query logic as you wish.
But if sorting is enable then this will not produce accurate results.
I am passing the PageNumber and PageSize to a stored procedure, which returns only that page of data. It also returns a record count what the total number of records would be if I returned all of them at once.
Generally, how do i hook this up to the DataGridView to enable paging?
It seems like the expectation is for the resultset to contain the complete dataset.
Many of the properties that I expect to be able to set, like RecordCount, appear to be read only.
Could someone give me general pointers?
I created a similar solution once, and adjusted a GridView (not sure if you mean a DataGrid or a GridView) to use server-side paging. The code is too much to post here and since there's no option for attachments here, you can download the code from http://www.raskenlund.com/downloads/GridView.zip
Check out the following article which describes the same thing:
http://www.highoncoding.com/Articles/210_GridView_Custom_Paging.aspx
I'm building a heavily CRUD based ASP.NET website and I've got to the phase of the project where I'm trying to build a search webpage that shows the user different subsets of a certain important table based on parameters they enter such as dates and different text fields.
I can't use a fixed SQL statement, because depending on whether they search by date or by something else, the SQL would be different, so instead I have been generating a results list using a table web control that starts out invisible and then is filled and set to visible once the user identifies a search they want to make. I used a table control because its easy to create and modify in the code behind, and I was able to make the needed calls to the database and populate that table as required.
However, the second thing I need with this search page, is the ability to allow the user to select a record from the results and then go edit it using the rest of the CRUD based pages on the site. To do that, I created asp:buttons in the table and gave them all different ids and the same event handler. But since I created the buttons dynamically, it seems the event disappears on callback and my scheme fails, so I'm taking a second look at how to do this.
My current code for the events looks like:
tempcell = new TableCell();
Button tempbutton = new Button();
tempbutton.Text = "Go";
tempbutton.ID = "gobutton" + rowN;
tempbutton.Visible = true;
tempbutton.Click += new EventHandler(tempbutton_Click);
tempcell.Controls.Add(tempbutton);
temprow.Cells.Add(tempcell);
My results table is declared like this:
<asp:Table ID="ResultTable" visible="false" runat="server"
GridLines="Both" CellSpacing="8">
</asp:Table>
I'd like to be able to identify which record the user selected, so I can send that info on to another page. And of course, I still need to be able to generate results for several different search criteria. Currently I have date, template and code based searches that lead to different stored procedures and different parameters based on what the user has entered.
Any suggestions on this? It seems like the data grids and repeaters require SQL statements in advance to work properly, so I'm not sure how to use them, but if I could then the item command approach would work with the buttons.
Your event will hook up successfully if the button is recreated in the page load event.
Otherwise, use a GridView. It is the perfect solution for simple CRUD, and you can control it as much as you need.
in all the datapager examples i've seen (using a LinqDataSource tied to a ListView) the queries to the database return the full recordset. how can i get JUST the page of rows that i want to display?
for example, if i have a table with 1million rows and i want to see the 10 results on page 5, i would be getting rows 51 to 60.
i'm sure i have to implement custom paging but i haven't found any good examples.
There are many ways of doing this, however, I personally like a SQL based solution that goes to the database and gets the result set. This 4GuysFromRolla Article does a good job of explaining it.
If you're using MSSql2005, take a look at this article.
As you can see, the trick is to use the function ROW_NUMBER(), that allow you to get the sequential number of a row in a recordset. With it you can simply enable pagination based upon the number of rows you want to get in a page.
I was under the impression (from Scott Guthie's blog post "LINQ to SQL (Part 9)") that the LinqDataSource handles the paging for you at the database level:
One of the really cool things to notice above is that paging and sorting still work with our GridView - even though we are using a custom Selecting event to retrieve the data. This paging and sorting logic happens in the database - which means we are only pulling back the 10 products from the database that we need to display for the current page index in the GridView (making it super efficient).
(original emphasis)
If you are using some custom paging, you can do something like this in LINQ to SQL:
var tagIds = (from t in Tags where tagList.Contains(t.TagText) select t.TagID).Skip(10).Take(10).ToList();
This is telling LINQ to take 10 rows (equivalent to T-SQL "TOP 10"), after skipping the first 10 rows - obviously these values can be dynamic, based on the Page Size and page number, but you get the idea.
The referenced post also talks about using a custom expression with a LinqDataSource.
Scott has more information on Skip/Take in Part 3 as well.