Hi,
I have a ObjectDataSource bound to the grid, the initial data load selects the data from the database 4 times using the same select statement, I have tried setting the datasource at runtime and design time with the same results in both cases. I know its not the ObjectDataSource because when I bind it to the standard .NET GridView it only selects the data once.
Secondary problem to this is: I have the webgrid in a warp panel, when sending an asynchronous postback using the warp panel, the webgrid then refreshes the data in the grid 4 times using the same select statement before processing the update/insert/delete operation. This seems excesive and totaly unwanted and unnecessary. The side effect from this is that it retrieves my concurrency control column from the database when it should be using the value that is in the grid.
Any one else have these sorts of problems with the grid?
Thanks
It seems a bit unusual that the grid should be calling select on your data multiple times. It's hard to guess why this is happening without knowing more about your project. The best thing to do would be to take the problem to developer support. They'll be able to help you diagnose what's going wrong.
The grid will refresh the data on each postback. It does this so that it doesn't have to store the row information in ViewState. It shouldn't be doing it four times though, only once. The ObjectDataSource has a caching option (I think the property is called AllowCache) that you might be able to use to avoid having to go back to the database on each postback.
Hi Helen,
Thanks for your response, I have submitted the problem with the select statement running 4 times to deleoper support, hopefully they will be able to shed some light on the issue.
With the data refresh, the problem is that it is refreshing the data before processing the update statement and then again after the update statement.
Here is the scenario:
The data in the grid is now in a detached scenario, I am using a Timestamp column to control concurrency.
I update 1 of the columns in the row, send the postback, the grid retrieves all the data from the database (select *) then performs the update. The problem is that it keeps the data which the user modified on the front end, but replaces all the other data it just retrieved from the database including a new value for my Concurrency control column (It has to keep the old value for the concurrency to work). So now the update works fine but I was expecting a Concurrency Exception to appear because another user modified the data and the current user's data is now stale.
eg.
User 1: Modified CustomerPhone to '98765'
User 2: Modified CustomerPhone to '123345'
User 2: Saved his change which caused the Timestamp column to update.
User 1: Saved his change (The Grid reloaded the data from the DB, but replaced '123345' with '98765', and because it retrieved the new Timestamp, it then performed an update using the new Timestamp - Which is wrong)
User 1: Should have received a concurrency exception, but instead has his data saved - Which appears to be a Last in wins scenario.
The grid should not refresh the data befor performing a update, after the update is fine.
Hope this makes sense.
I finally figured out what the problem is...
I was using an objectdatasource connected to my business layer class, the select procedure was returning an IEnumerable<Customer> list, when I changed this to List<Customer> most of my problems went away. It appears that the ultrawebgrid can't handle IEnumerable<>, I also tried IQueryable<> and Table<>, all of which had the same problems (all of these however worked fine with the standard asp.net GridView control)
By changing the result to use List<Customer> the database select was only being executed once instead of 4 times, and the cache functionaly started working with the UltraWebGrid.
The cache on the objectdatasource did not solve my problem because when the data was changed by another user, the cache would automatically become invalidated as it should, this would then cause the objectdatasource to select directly from the database instead of the cache and thus my problem of the grid retrieving the data from the database before running the update did not go away.
I gave up on using the objectdatasource and decided to control everything manually in the code behind, i persisted the List<Customer> in session state to retain all the original values.
I would have expected the caching to work with the grid. I don't think it's doing anything that would override the cache settings. It just asks the ObjectDataSource for some data, it doesn't really care where it comes from. I tried with a simple example, hooking the ObjectDataSource up to a DataSet to be displayed in a vanilla grid and it seemed to be working ok.
This is another issue that would be best handled by developer support because they'll be able to help to figure out exactly what's going on in your project.
In that case, is there any way to stop the grid from refreshing 1 column before the update.
ie. If i wanted to keep the Timestamp column's original value and make sure it is not overwritten by the refresh before the update, how would I go about this? Keeping in mind that I would need to get the fresh result of the Timestamp column after the update.
I tried to use the caching of the objectdatasource by setting EnableCaching to true and CacheDuration to 30 according the MSDN help for enabling caching on an ObjectDataSource but for some reason this did not enable caching. It still went to the database for every select and refresh of the data. Could the grid be overriding this somehow?
The grid has to refresh the data before performing the update because it's not storing the information in the rows anywhere. The grid can't process the update until it has gotten a fresh lot of data because otherwise it won't be able to check whether the value has really changed and it won't be able to pass a reference to the row that is being updated because it won't have any rows.
The grid originally persisted all the row information to viewstate so it could rebuild itself without going back to the data source. The problem was that this generated a lot of viewstate. To get around this, the when the grid binds to a DataSource control, it recreates the rows from the data source on each postback so it doesn't have to store all the information in viewstate.
For a situation like yours, where you need the grid to have access to the old data, you'll need to persist the data source information somewhere between postbacks and then pass it back to the grid on postback. The easiest way to do that is just to enable caching on the ObjectDataSource, but if you need something special you might need to write some code to persist it yourself.
It shouldn't be updating again after the update has been processed. It should only be binding to the rows once before Page_Load happens unless you're explicitly binding again to get some fresh data.
I ran into this or a very similar issue using an Object Data Source with the WebGrid. In my case, it calls the ODS twice, but only when sorting or changing pages. If I merely refreshed the page, which caused a rebind of the data, then the ODS was called once. I saw that the first call to the ODS was with the previous set of parameters (old sort column, or old page number). The second call to the ODS would have the correct params. Also like you, If I used a standard .NET gridview control, it worked correctly.
I had logged this issue with developer support about 8 months ago, back in April of 2007. It was reproduced by the support engineer and assigned a bug report # of BR22107, which has been in a state of "In Dev" for about 7 months... I am still seeing this issue, so I figure spreading the word can only help push for a more timely fix.