I'm encountering a performance issue when I bind a dataset to a datagrid at runtime. Regardless of the speed of the initial data population, when I issue a "refresh" request, the dataset with the exact same query/results is taking twice as long to bind to the grid. I've read the document in this site that talks about a lot of the WinGrid performance issues and have tried a number of the suggestions with no success.
The logic follows a certain flow:
- separate routine populates a dataset (mygrdxData)
- if there are results, the SetDataBinding is executed to binds that data to the datagrid (see snippet below)
In the first execution the binding process takes about 5 seconds (1000 records with about 60 columns). The second execution takes about 11 seconds (same record, column count and actual data).
Why the doubling of time spent in SetDataBinding on requests subsequest to the first request? What can I do to eliminate this and/or reset grid back to "original state"?
Dim iTick As Integer = GetTickCount
grdx.DataBindings.Clear() : MaxRows = 0If gfIsArrayFull(mygrdxData) OrElse (Not IsNothing(mygrdxData) AndAlso mygrdxData.Tables.Count > 0 AndAlso mygrdxData.Tables(0).Columns.Count > 0) Then 'grdx.DisplayLayout.MaxBandDepth = 1 : grdx.SyncWithCurrencyManager = False grdx.SetDataBinding(mygrdxData, mygrdxData.Tables(0).TableName, False) MaxRows = mygrdxData.Tables(0).Rows.CountEnd IfDebug.WriteLine("SetDataBinding(ms): " & CStr(GetTickCount - iTick))
Hi,
What exactly do you mean when you say "refresh" request? I assume you mean that the same code you have here is being called again, so you are re-setting the grid's DataSource and DataMember to the same values?
Out of curiosity - why do that? It's usually best to avoid doing that if you can, since you will lose all state information for any rows in the grid.
Anyway... my guess is that the extra time is because the first time you bind the grid, it simply has to create the bands, columns, and rows. The second time you bind the grid, it not only has to create new objects, it has to dispose of all of the existing objects.
Doubling the time seems a bit excessive for that process, so it might not be as efficient as it could be, but that's the only thing I can think of that would cause an increase in time.
To verify that, you could break up the process by setting the grid's DataSource to null first and seeing if that takes 6 seconds and therefore accounts for the extra time.
Either way, if you would like to post a small sample project here which demonstrates the behavior you are getting, I'd be happy to check it out and we can see if there is anything we (or you) can do to improve the performance.
To answer "refresh" question - yes, the grid is attached to a specilized "filter" control which allows our user(s) to change conditions of the query before displaying results in the datagrid. "Refresh" option is provided so that the user can issue the same query command to "see" any changes that may have been done by other users.
The result of the query returns an ADO recordset which is then bound to the datagrid. In this particular example, I simply issued the "refresh" command to eliminate the issue that bind may be different due to different records/data within records in the ADO recordset (thinking the bind time would be identical if not close since it is the same # of records and same data in the records).
I modified the code as you suggested (set grid datasource to nothing prior to the binding) - didn't make a difference to the binding time in the second call (see below).
What did you mean by ... "it not only has to create new objects, it has to dispose of all of the existing objects". What objects is it disposing? Is there some way to issue these same/similar commands prior to the SetBinding to eliminate the grid from having to interpret this action on the fly and/or record the grid state prior to the first binding and the (re)set it back to that state state prior to subsequent calls?
As to posting a small project, can't really do this since it involves our filter control and this turns your request into a rather large exercise. I did create a project that simulates similar characteristics (ie, bind 1000 records with 200 columns) BUT it does not show the same behaviour - original load time is quick and subsequent calls are even quicker. Does this have something to do with the dataset being bound, i.e., one from an ADO call to SQL versus one that is contructed in memory?
Thanks
Code Snippet:
Dim iTick As Integer = GetTickCountIf gfIsArrayFull(mygrdxData) OrElse (Not IsNothing(mygrdxData) AndAlso mygrdxData.Tables.Count > 0 AndAlso mygrdxData.Tables(0).Columns.Count > 0) Then grdx.DataSource = Nothing Debug.WriteLine("ClearBinding(ms): " & CStr(GetTickCount - iTick))
iTick = GetTickCount grdx.SetDataBinding(mygrdxData, mygrdxData.Tables(0).TableName, False) MaxRows = mygrdxData.Tables(0).Rows.CountElse grdx.DataSource = Nothing MaxRows = 0End IfDebug.WriteLine("SetDataBinding(ms): " & CStr(GetTickCount - iTick))
First Call:
ClearBinding(ms): 0
SetDataBinding(ms): 5990
Second Call:
SetDataBinding(ms): 11762