They seem to be so nasty.
I have a gridview, and the query it runs pulls back 10,000 results if no filters are set... and displays 10 of them on the first page. You press page 2, and then it does the query again... and again...
Isn't there a way to cache them? Isn't there a much easier way to bring in all the results then filter them live without repeated queries? Must ASP.NET be all about a struggle against the gridview?
I would love to know if there is a better way...
Which grid are you using? GridViews will bind to anything that implements IEnumerable, so do you realise that you can fetch the data and explicitly bind it yourself? Similar to:
List<myDataObjects> data = executeMyQuery();
gridview.DataSource = data;
gridView.DataBind();
this way you can control when the data is fetched, and you can even cache it if required.
If you're using SQL Server 2005 and above, you can make use of the ROW_NUMBER() function in your query, which you can use to page the rows returned at source.
ScottGu has a detailed blog post here using a DataList, but this is equally applicable to GridViews
This blog entry has a more concise introduction to the specifics of ROW_NUMBER()
Instead of performing a query which returns everything in one big resultset, consider returning your results in a paged fashion.
You can put the results in the ViewState, but this isn't really advisable if you have a lot of data which can be returned.
Use a repeater and create your queries to only return the results you need. Your query will probably need to make use of parameters for resultsPerPage and PageNumber.
Gridviews connected to those datasets are good for 5 minute demos, but really shouldn't end up in production code. Nasty is good word for it.
Related
I have a DataGrid I'm binding to a DataTable, and displaying three BoundColumns as a result.
I would like to have a fourth column that connects with different data-- for instance, if column #3 in the DataGrid is a UserID, I would like to use that to query against a database and retrieve the user's first name, and display it in the fourth column.
Are there any recommended approaches to this? I'm not a DataGrid expert but should I be looking at a TemplateColumn or something along those lines?
Which event should I hook all this querying to, OnItemDataBound?
The recommended approach is return the user's first name as part of the original query and just use a BoundColumn. If you need to modify data before displaying, then yes you can use a TemplateColumn and the OnItemDataBound event to manipulate your data.
Running queries OnItemDataBound is not something I would ever encourage. So if your grid will show 100 records at once, you want to run 100 extra queries per page load? This is something that if you implement, could possibly run within reason during testing. Once under load though, you'll see have hundreds of extra queries running isn't a good idea... it can just be solved by fixing the original query or maybe making a denormalized table depending on your DB structure and the complexity of your query.
When I ran into similar issue, I went the denormalized table route.
Use a join in your sql statement to get the other value.
I'm populating a GridView with code, setting datasource to the dataset returned by a query. So apparently sorting and paging don't just work magically like if I use a datasourceid= some sqldatasource.
I've found a number of examples of how to do this on the web, but they all appear to re-execute the query every time. Shouldn't the contents of the query be saved in the view state? Is there some way to just get the previous query results and re-sort without having to go back to the database? (Is it saving all the data in the view state? If so, why can't I get to it? It seems pretty dumb to send it all to the user's browser and send it all back, wasting all the bandwidth, if there's no way to get to it.)
Also, if I try to allow paging, it appears I again have to re-execute the query every time the user goes to another page. And if the user sorts and then pages, then I have to remember what the sort order was in a hidden field or some such, so I can re-read the data, re-sort, and then go to the right page.
Given that when you use a data source control all this behavior is built in, I think I'm missing something here. But given all the examples out there that do it this slow, hard way, if I'm missing something, a lot of other programmers are missing it, too.
If you're using an ASP.NET GridView control every time you sort a column or page through the data set then you're making a server postback. Sorting and paging with this particular control has never worked 'magically' and has long been a bugbear of mine.
You can speed things up by storing the data source that you're building the grid from in memory, either as a session or through the ViewState. Both have pros and cons and I suggest you read up.
If at all possible I suggest forgetting the ASP.NET GridView and looking at a client side solution such as the jQuery jqGrid. It uses AJAX calls to sort and page and is much, much faster and less of a headache. The only drawback is the learning curve but believe me it's worth it in the long run.
Yes the gridview re-execute the query every time.
If the query takes too long, you can manually store data in the session, or ViewState. And in the Algorithm that populates the grid just read them directly for it, instead of running the query.
you can, in the page load event, run the query one time when there is no postback (you can check for postback with
if (!Page.IsPostBack){
//Run the query and save it to the session
}
and the the method that populate the grid, should read from the session directly. no need to run the query again
I have a client who wants to return an ENORMOUS query from a web service, and will not budge. They are adamant that the query must be able to return absolutely everything, and they also will not allow us to do any sort of server side paging.
We have it working so that it returns all the data just fine, and we have it displayed in an ASP.NET GridView. In order to speed up the rendering of the huge grid, we decided to implement client-side paging, but I'm not exactly sure how to go about this.
Currently, we store the whole of the data in the ViewState, and then page and sort based off of that so as to avoid hitting the server again.
However, with the default set up, when trying to select any page but the first, it returns a 404 error. I'm guessing this is because it times out while trying to send the enormous data set via the ViewState.
Is there any sort of way to return the data set, and then do all of the paging and sorting all on the client without having to do any sort of post back? Or is there some other way to do this that we haven't thought of? (besides server side paging. We would LOVE to do it this way because it is so obviously the right way, but the client won't budge...)
EDIT: I would like to stick to the ASP.NET GridView control if at all possible. We've found a couple different options like jQuery and the like, but we have a lot of things to change if we change to a different type of control. So I'd like to avoid changing that if at all possible.
If the time is not a big problem for you the time it takes to get all the records from the database and I believe that on the client side the grid is typically renders as an HTML table than you can use a jquery plugin that will paginate the table on the client side.
http://www.codeproject.com/KB/webforms/clientside_gridviewpaging.aspx
We've run into situations where the Viewstate itself becomes a performance issue, and had to come up with ways to address a similar situation...
Your options depend greatly on some details which aren't included in the question.
For example? How often does the data from the webservice change? You may be able to do one of the following:
Save the results in Cache or Session (not a good idea if the results are that large...)
Serialize the result to an Xml file and read from that while paging
Import the data periodically into a SQL database, or into a temp table in a SQL database, with some identifier to tie the data to the user.
I've had good luck using the jquery tablesorter plugin. It gives some great options.
http://tablesorter.com/docs/
I have a gridview with about 300-400 rows that I use for reporting; it needs paging and requires sorting. My choice is between these two options: a) load the 300-400 in one query and let the gridview do the paging and sorting; b) handle the paging/sorting at the data source level. I know that b) is going to be better/faster/more efficient... In my context, I'm looking to get something done relatively fast; if I choose a), will the page seem incredibly/painfully slow?
Thanks.
Use the builtin functions of the GridView and load the whole data at one go. It wouldn't be worth the effort to implement paging in database(f.e. with RowNumber) when your number of records is such small, especially because you mentioned that you are looking for a fast solution. When you enable paging in GridView the performance will suffice.
read Scott Guthrie's excellent article about paging.
How to implement a data-result search page built with ASP.NET 2.0 and Atlas that can present hundreds of thousands of row results using the ASP.NET 2.0 GridView control. The results are formatted using a “paging” based UI model – where 15 results per page are displayed, and the user can skip from page to page to see their data. For kicks I also added support for editing and deleting each individual row.
Although 300-400 rows isn't a particularly large set of data, I would certainly vote for option B since it will definitely be more scalable. Once you start getting massive sets of data, loading all of it with one query and having the GridView handle the paging will end up being incredibly slow. The better option is to, like you said, only query the data you need for each page.
However, if you aren't going to have data sets larger than 300-400 records, you probably don't need to be too concerned about load times, but again, the key is in scalability.
Here's my scenario:
1) User runs search to retrieve values for display in ListView via LinqDataSource.
2) They click on one of the items which takes them to another page where the details can be examined, further drill-down can happen, etc.
3) User wants to go back to the original ListView results to select another item for inspection.
I can see it's possible to pass the querystring params around, allowing the querying to be duplicated each time the user comes back to the ListView, but it seems like there ought to be a way to cache the results.
Since I'm using the LinqDataSource, though, I believe the actual results are fetched each time the query is run. I'm currently feeding a "select new {blah, blah}" type of IEnumerable to the e.Results, which can't be turned into a List since it's populated with anonymous types.
In short:
1) Does it make sense to try to place potentially large query results in the users session?
2) If it does, is a List the reasonable data structure?
3) Do I need to resort to something like creating a class with the correct properties to hold the anonymous data, enumerate the query return, populate the List?
4) Is there a better option than the LinqDataSource for this type goal?
5) Or, does it just make more sense to run the query each time they hit the ListView?
I apologize if this wasn't clear. I would really appreciate it if someone can set me straight before I nuke a bunch of my free time headed down the wrong path :)
First, I would suggest that you look into the caching mechanism that comes with ASP.NET, unless the data is private for a certain user.
Second, I would suggest that you design your application in a way so that you create natural points where you could try to get data from a cache before querying the database (and insert data into the cache, with expiration rules), but don't start putting stuff into the cache until you have verified that it will actually make a difference.
Measure how much time that is actually spent on retrieving data and use caching in the cases where it makes a difference.
I'm not sure if resurrecting threads from the dead is cool on SO, but here is what I found to answer this question:
http://weblogs.asp.net/pwelter34/archive/2007/08.aspx